当前位置: 首页 > news >正文

二次封装 Vuex for Uniapp 微信小程序开发

作为高级前端开发工程师,我将为你提供一个针对 Uniapp + Vue2 + Vuex 的 Store 二次封装方案,使团队成员能够更便捷地使用和管理状态。

封装目标

  1. 模块化管理状态

  2. 简化调用方式

  3. 提供类型提示(在 Vue2 中尽可能实现)

  4. 便于维护和查找

封装方案

1. 目录结构重构

首先,我们重构 store 的目录结构:

store/
├── index.js              # 主入口文件
├── modules/              # 模块目录
│   ├── user.js           # 用户模块
│   ├── cart.js           # 购物车模块
│   └── ...               # 其他模块
└── store-utils.js        # 封装的工具方法

 2. 主入口文件封装 (store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'
import * as utils from './store-utils'Vue.use(Vuex)// 自动加载 modules 目录下的所有模块
const modules = utils.autoLoadModules()const store = new Vuex.Store({modules,// 全局配置strict: process.env.NODE_ENV !== 'production'
})// 挂载工具方法到 Vue 原型
Vue.prototype.$storeUtils = utilsexport default store

3. 工具方法封装 (store/store-utils.js)

/*** 自动加载 modules 目录下的所有模块*/
export function autoLoadModules() {const modules = {}const requireModule = require.context(// 搜索目录'./modules',// 是否搜索子目录false,// 匹配文件的正则/\.js$/)requireModule.keys().forEach(fileName => {// 获取模块名(去掉文件扩展名)const moduleName = fileName.replace(/(\.\/|\.js)/g, '')modules[moduleName] = {namespaced: true,...requireModule(fileName).default}})return modules
}/*** 简化 mapState 调用* @param {string} moduleName 模块名* @param {Array|Object} states 状态名数组或对象*/
export function mapState(moduleName, states) {if (!moduleName) return {}if (Array.isArray(states)) {const result = {}states.forEach(key => {result[key] = function() {return this.$store.state[moduleName][key]}})return result}// 对象形式const result = {}Object.keys(states).forEach(key => {result[key] = function() {return this.$store.state[moduleName][states[key]]}})return result
}/*** 简化 mapGetters 调用* @param {string} moduleName 模块名* @param {Array|Object} getters getter名数组或对象*/
export function mapGetters(moduleName, getters) {if (!moduleName) return {}const namespace = moduleName + '/'if (Array.isArray(getters)) {const result = {}getters.forEach(getterName => {result[getterName] = function() {return this.$store.getters[namespace + getterName]}})return result}// 对象形式const result = {}Object.keys(getters).forEach(key => {result[key] = function() {return this.$store.getters[namespace + getters[key]]}})return result
}/*** 简化 mapMutations 调用* @param {string} moduleName 模块名* @param {Array|Object} mutations mutation名数组或对象*/
export function mapMutations(moduleName, mutations) {if (!moduleName) return {}const namespace = moduleName + '/'if (Array.isArray(mutations)) {const result = {}mutations.forEach(mutationName => {result[mutationName] = function(payload) {this.$store.commit(namespace + mutationName, payload)}})return result}// 对象形式const result = {}Object.keys(mutations).forEach(key => {result[key] = function(payload) {this.$store.commit(namespace + mutations[key], payload)}})return result
}/*** 简化 mapActions 调用* @param {string} moduleName 模块名* @param {Array|Object} actions action名数组或对象*/
export function mapActions(moduleName, actions) {if (!moduleName) return {}const namespace = moduleName + '/'if (Array.isArray(actions)) {const result = {}actions.forEach(actionName => {result[actionName] = function(payload) {return this.$store.dispatch(namespace + actionName, payload)}})return result}// 对象形式const result = {}Object.keys(actions).forEach(key => {result[key] = function(payload) {return this.$store.dispatch(namespace + actions[key], payload)}})return result
}/*** 创建模块的快捷访问方式* @param {string} moduleName 模块名*/
export function createModuleHelpers(moduleName) {return {state: (stateName) => {return this.$store.state[moduleName][stateName]},getter: (getterName) => {return this.$store.getters[`${moduleName}/${getterName}`]},commit: (mutationName, payload) => {this.$store.commit(`${moduleName}/${mutationName}`, payload)},dispatch: (actionName, payload) => {return this.$store.dispatch(`${moduleName}/${actionName}`, payload)}}
}

4. 模块示例 (store/modules/user.js)

const state = {token: '',userInfo: null,isLogin: false
}const getters = {getUserName: state => {return state.userInfo?.name || ''},getUserId: state => {return state.userInfo?.id || ''}
}const mutations = {SET_TOKEN(state, token) {state.token = token},SET_USER_INFO(state, userInfo) {state.userInfo = userInfostate.isLogin = !!userInfo},CLEAR_USER(state) {state.token = ''state.userInfo = nullstate.isLogin = false}
}const actions = {login({ commit }, { username, password }) {return new Promise((resolve, reject) => {// 模拟登录请求uni.request({url: '/api/login',method: 'POST',data: { username, password },success: (res) => {commit('SET_TOKEN', res.data.token)commit('SET_USER_INFO', res.data.userInfo)resolve(res.data)},fail: (err) => {reject(err)}})})},logout({ commit }) {commit('CLEAR_USER')return Promise.resolve()}
}export default {state,getters,mutations,actions
}

使用方式

1. 组件中使用

import { mapState, mapGetters, mapMutations, mapActions } from '@/store/store-utils'export default {computed: {// 传统方式...mapState('user', ['token', 'userInfo', 'isLogin']),...mapGetters('user', ['getUserName', 'getUserId']),// 或者使用对象形式...mapState('user', {myToken: 'token',myUserInfo: 'userInfo'})},methods: {...mapMutations('user', ['SET_USER_INFO']),...mapActions('user', ['login', 'logout']),// 示例方法handleLogin() {this.login({ username: 'test', password: '123456' }).then(() => {uni.showToast({ title: '登录成功' })}).catch(err => {uni.showToast({ title: '登录失败', icon: 'none' })})}}
}

2. 快捷访问方式

export default {methods: {someMethod() {// 使用快捷访问const userHelpers = this.$storeUtils.createModuleHelpers('user')// 获取状态const token = userHelpers.state('token')// 获取getterconst userName = userHelpers.getter('getUserName')// 提交mutationuserHelpers.commit('SET_USER_INFO', { name: '张三' })// 分发actionuserHelpers.dispatch('logout').then(() => {console.log('登出成功')})}}
}

3. 在JS文件中使用

import store from '@/store'// 直接使用store
const token = store.state.user.token// 提交mutation
store.commit('user/SET_TOKEN', 'new-token')// 分发action
store.dispatch('user/login', { username: 'test', password: '123456' }).then(() => {console.log('登录成功')})

最佳实践建议

  1. 命名规范

    • 模块名使用小驼峰命名法 (user, shoppingCart)

    • state 属性使用小驼峰命名法

    • mutations 使用大写蛇形命名法 (SET_USER_INFO)

    • actions 使用小驼峰命名法

  2. 文档注释
    在每个模块文件顶部添加注释说明模块用途,重要的 state、getter、mutation 和 action 添加注释

  3. 模块拆分

    • 按业务功能拆分模块

    • 避免单个模块过大

相关文章:

  • npm error Cannot find module ‘negotiator‘ 的处理
  • Turf.js:前端地理空间分析的瑞士军刀
  • 网络编程3
  • 图论回溯
  • 【监控】Spring Boot 应用监控
  • 如何制作全景VR图?
  • 线上 VR 展会:独特魅力与显著特质
  • 【赵渝强老师】HBase的体系架构
  • VR 技术与病毒分离鉴定:一场奇妙的邂逅​
  • Mobaxterm 连接到 Docker 容器
  • C语言栈详解
  • 不同电脑同一个网络ip地址一样吗
  • ⚡ Hyperlane —— 比 Rocket 更快的 Rust Web 框架!
  • IEEE出版|2025年智能制造、机器人与自动化国际学术会议 (IMRA2025)
  • 晶体单元(crystal unit)与晶体振荡器(crystal oscillator)
  • 类和对象(3)
  • vscode开发stm32,main.c文件中出现很多报错影响开发解决日志
  • 智能防护实战:从攻击成本看企业安全降本增效
  • 分布式架构:解读不同数据一致性模型
  • stm32f系列工程切换到H系列
  • 平潭建设局网站/seo的中文含义是什么意思
  • 昌网站建设/佛山快速排名
  • 网站建设专题/线上推广策略
  • 做网站策划的工具/指数基金排名前十名
  • 苏州360推广网站建设/线上宣传渠道
  • 前端做项目网站/杭州seo外包