{{wikiTitle}}
CRMEB前端状态管理说明
目录:
CRMEB前端状态管理说明
概述
CRMEB项目采用了Vue.js生态系统中的Vuex作为前端状态管理解决方案。项目包含两个前端应用:后台管理系统(admin)和移动端应用(uniapp),两者都使用了类似的Vuex模式,但根据各自的特点进行了定制化实现。
后台管理系统状态管理(admin)
架构设计
后台管理系统采用模块化的Vuex架构,主要特点如下:
- 根Store配置:位于
view/admin/src/store/index.js- 引入Vuex并注册到Vue实例
- 导入admin模块作为命名空间
- 使用模块化组织状态,便于维护
import Vue from \'vue\';
import Vuex from \'vuex\';
import admin from \'./modules/admin\'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
admin
}
})
- 模块化结构:
view/admin/src/store/modules/admin/index.js- 动态导入所有子模块
- 使用命名空间组织状态
- 便于扩展和维护
/**
* 该文件启用 `@/store/index.js` 导入所有 vuex 模块。
* 这个文件是一次性创建的,不应该被修改。
*/
const files = require.context(\'./modules\', false, \\/\\.js\\$/);
const modules = {};
files.keys().forEach(key => {
modules[key.replace(/(\\.\\/|\\.js)/g, \'\')] = files(key).default
});
export default {
namespaced: true,
modules
};
主要模块
1. 用户认证模块(account)
负责处理用户的登录、注册、登出等认证相关操作。
export default {
namespaced: true,
actions: {
/**
* @description 登录
* @param {Object} param context
* @param {Object} param username {String} 用户账号
* @param {Object} param password {String} 密码
* @param {Object} param route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式
*/
login({ dispatch }, { username = \"\", password = \"\" } = {}) {
return new Promise((resolve, reject) => {
// 开始请求登录接口
AccountLogin({
username,
password,
})
.then(async (res) => {
// 设置 cookie 一定要存 uuid 和 token 两个 cookie
// 整个系统依赖这两个数据进行校验和存储
// uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复
// token 代表用户当前登录状态 建议在网络请求中携带 token
// 如有必要 token 需要定时更新,默认保存一天,可在 setting.js 中修改
// 如果你的 token 不是通过 cookie 携带,而是普通字段,也可视情况存储在 localStorage
util.cookies.set(\"uuid\", res.uuid);
util.cookies.set(\"token\", res.token);
// 设置 vuex 用户信息
await dispatch(\"admin/user/set\", res.info, { root: true });
// 用户登录后从持久化数据加载一系列的设置
await dispatch(\"load\");
// 结束
resolve();
})
.catch((err) => {
reject(err);
});
});
},
/**
* @description 退出登录
* */
logout({ commit, dispatch }, { confirm = false, vm } = {}) {
async function logout() {
AccountLogout()
.then(() => {
// localStorage.clear();
// sessionStorage.clear()
let isAgentAdmin = Vue.prototype.__isAgentPath();
if (isAgentAdmin) {
util.cookies.remove(\"agent_token\");
util.cookies.remove(\"agent_uuid\");
// 删除localStorage
store.dispatch(\"admin/db/databaseClear\", {
user: true,
isAgent: true
});
} else {
util.cookies.remove(\"token\");
util.cookies.remove(\"expires_time\");
util.cookies.remove(\"uuid\");
// 删除localStorage
store.dispatch(\"admin/db/databaseClear\", {
user: true,
});
// 清空 vuex 用户信息
dispatch(\"admin/user/set\", {}, { root: true });
}
// 跳转路由
router.push({
name: isAgentAdmin ? \"agentLogin\" : \"login\",
});
})
.catch(() => {});
}
if (confirm) {
Modal.confirm({
title: vm.$t(\"basicLayout.logout.confirmTitle\"),
content: vm.$t(\"basicLayout.logout.confirmContent\"),
onOk() {
logout();
},
});
} else {
logout();
}
}
}
};
2. 用户信息模块(user)
管理用户的基本信息、权限等数据。
3. 布局配置模块(layout)
管理系统的界面布局配置,如菜单折叠状态、全屏模式等。
export default {
namespaced: true,
state: {
...Setting.layout,
isMobile: false, // 是否为手机
isTablet: false, // 是否为平板
isDesktop: true, // 是否为桌面
isFullscreen: false, // 是否切换到了全屏
copyrightShow: true, // 是否显示底部版权
menuCollapse: JSON.parse(window.localStorage.getItem(\'menuCollapse\')) || false //侧边菜单栏是否默认折起
},
mutations: {
/**
* @description 设置设备类型
* @param {Object} state vuex state
* @param {String} type 设备类型,可选值为 Mobile、Tablet、Desktop
*/
setDevice (state, type) {
state.isMobile = false;
state.isTablet = false;
state.isDesktop = false;
state[`is${type}`] = true;
},
/**
* @description 修改 menuCollapse
* @param {Object} state vuex state
* @param {Boolean} collapse 折叠状态
* */
updateMenuCollapse (state, collapse) {
let storage = window.localStorage;
storage.setItem(\'menuCollapse\', collapse);
state.menuCollapse = collapse;
},
/**
* @description 设置全屏状态
* @param {Object} state vuex state
* @param {Boolean} isFullscreen vuex
* */
setFullscreen (state, isFullscreen) {
state.isFullscreen = isFullscreen;
}
},
actions: {
/**
* @description 切换全屏
*/
toggleFullscreen ({ commit }) {
return new Promise(resolve => {
if (screenfull.isFullscreen) {
screenfull.exit();
commit(\'setFullscreen\', false);
} else {
screenfull.request();
commit(\'setFullscreen\', true);
}
resolve();
});
}
}
};
4. 数据库模块(db)
提供本地数据持久化功能。
状态管理最佳实践
- 命名空间:所有模块都使用命名空间避免冲突
- 状态持久化:通过localStorage保存用户偏好设置
- 异步操作:使用actions处理异步请求
- 状态同步:通过mutations确保状态变化可追踪
移动端状态管理(uniapp)
架构设计
移动端应用同样采用Vuex进行状态管理,结构更加轻量化:
- 根Store配置:位于
view/uniapp/store/index.js- 导入模块和getter
- 在非生产环境中启用严格模式
import Vue from \"vue\";
import Vuex from \"vuex\";
import modules from \"./modules\";
import getters from \"./getters\";
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== \"production\";
export default new Vuex.Store({
modules,
getters,
strict: debug
});
- 模块组织:
view/uniapp/store/modules/index.js- 集中导出所有模块
import app from \"./app\";
import hotWords from \"./hotWords\";
import indexData from \'./indexData.js\'
export default {
app,
hotWords,
indexData
};
主要模块
1. 应用主模块(app)
管理用户认证、用户信息、个性化配置等核心状态:
import { getUserInfo } from \"@/api/user.js\";
import { diyProductApi } from \"@/api/store.js\"
import { getAgentBrokerage } from \"@/api/public.js\"
import {
LOGIN_STATUS,
NON_WIFI_AUTOPLAY,
UID,
USER_INFO,
STORE_NUM,
STORE_STAFF_INFO,
} from \'@/config/cache\';
import Cache from \'@/utils/cache\';
const state = {
token: Cache.get(LOGIN_STATUS) || false, // 用户认证令牌
backgroundColor: \"#fff\", // 背景色
userInfo: Cache.get(USER_INFO) || {}, // 用户信息
uid: Cache.get(UID) || 0, // 用户ID
homeActive: false, // 首页激活状态
phoneStatus: true, // 电话状态
pageFooter: uni.getStorageSync(\'pageFoot\') || {}, // 页面底部
autoplay: Cache.get(NON_WIFI_AUTOPLAY) || false, // 自动播放设置
// 商品详情可视化数据
diyProduct: {
navList: [0, 1, 2, 3, 4], // 顶部菜单内容
openShare: 1, //是否开启分享
pictureConfig: 0, //轮播图模式 0 固定方图 1 高度自适应
swiperDot: 1, //是否展示轮播指示点
showPrice: [0, 1], //是否显示付费会员价和等级会员
isOpen: [0, 1, 2], //是否展示 0 划线价 1 累计销量 2 库存
showSvip: 1, //是否展示付费会员卡片
showRank: 1, // 是否展示排行榜卡片
showService: [0, 1, 2, 3], //服务区卡片 0 营销活动入口 1 sku选择 2 服务保障 3 参数
showReply: 1, //是否展示评论区
replyNum: 3, //评论数量
showMatch: 1, //是否展示搭配购
matchNum: 3, //搭配套餐数量
showRecommend: 1, //是否展示推荐商品
recommendNum: 12, //推荐商品数量
menuList: [0, 1, 2], //底部左侧菜单
showCart: 1, //是否显示购物车
showCommunity: 0, //是否显示种草
},
// 商品分类可视化数据
diyCategory: {
level: 2,
index: 0
},
productVideoStatus: true, // 产品视频状态
nearbyStore: 0, // 附近门店
storeNum: Cache.get(STORE_NUM) || 0, // 门店类型
storeStaffInfo: Cache.get(STORE_STAFF_INFO, true) || {}, // 店员门店信息
brokerageFuncStatus: 0, // 分销启用状态
storeBrokerageStatu: 1, // 分销模式
storeBrokeragePrice: 0, // 满额分销最低消费金额
};
const mutations = {
SETPHONESTATUS(state, val) {
state.phoneStatus = val;
},
LOGIN(state, opt) {
state.token = opt.token;
Cache.set(LOGIN_STATUS, opt.token, opt.time);
},
SETUID(state, val) {
state.uid = val;
Cache.set(UID, val);
},
UPDATE_LOGIN(state, token) {
state.token = token;
},
LOGOUT(state) {
Cache.clear(LOGIN_STATUS);
Cache.clear(UID);
Cache.clear(USER_INFO);
Cache.clear(\'newcomerGift\');
state.token = undefined;
state.uid = undefined
state.userInfo = {}
},
BACKGROUND_COLOR(state, color) {
state.color = color;
document.body.style.backgroundColor = color;
},
UPDATE_USERINFO(state, userInfo) {
state.userInfo = userInfo;
Cache.set(USER_INFO, userInfo);
},
OPEN_HOME(state) {
state.homeActive = true;
},
CLOSE_HOME(state) {
state.homeActive = false;
},
FOOT_UPLOAD(state, data) {
state.pageFooter = data
},
SET_AUTOPLAY(state, data) {
state.autoplay = data
Cache.set(NON_WIFI_AUTOPLAY, data)
},
SET_PRODUCT_DIY(state, data) {
state.diyProduct = data.product_detail;
state.diyCategory = data.product_category;
state.productVideoStatus = data.product_video_status;
}
};
const actions = {
USERINFO({
state,
commit
}, force) {
if (state.userInfo !== null && !force)
return Promise.resolve(state.userInfo);
else
return new Promise(resolve => {
getUserInfo().then(res => {
commit(\"UPDATE_USERINFO\", res.data);
Cache.set(USER_INFO, res.data);
resolve(res.data);
});
}).catch(() => {
});
},
// div商品详情
async getDiyProduct({commit}) {
let result = await diyProductApi();
if(result.status == 200){
commit(\"SET_PRODUCT_DIY\",result.data);
}
},
// 获取分销信息
async getBrokerage({ commit }) {
let result = await getAgentBrokerage();
if (result.status == 200) {
commit(\"SET_BROKERAGE_STATUS\", result.data);
}
}
};
export default {
state,
mutations,
actions
};
2. 首页数据模块(indexData)
管理首页相关数据,如购物车数量等:
import {CART_NUM} from \'@/config/cache\';
import Cache from \'@/utils/cache\';
export default {
namespaced: true,
state: {
cartNum: Cache.get(CART_NUM) || 0
},
getters: {},
mutations: {
setCartNum(state, data) {
Cache.set(CART_NUM, data);
state.cartNum = data;
}
}
}
3. 热词模块(hotWords)
管理搜索相关的热词数据:
export default {
namespaced: true,
state: {
// 搜索关键字
hotWord: []
},
getters: {},
mutations: {
setHotWord(state, fastsearchforhotwords) {
state.hotWord = fastsearchforhotwords;
}
}
}
全局Getters
移动端提供了便捷的全局状态访问接口:
export default {
token: state => state.app.token,
isLogin: state => !!state.app.token,
backgroundColor: state => state.app.backgroundColor,
userInfo: state => state.app.userInfo || {},
uid: state => state.app.uid,
homeActive: state => state.app.homeActive,
home: state => state.app.home,
cartNum: state => state.indexData.cartNum,
diyProduct: state => state.app.diyProduct,
diyCategory: state => state.app.diyCategory,
productVideoStatus: state => state.app.productVideoStatus,
storeNum: state => state.app.storeNum
};
状态管理最佳实践
1. 状态持久化策略
- 后台管理:使用localStorage保存用户偏好设置(如菜单折叠状态)
- 移动端:使用自定义Cache工具类保存用户认证信息和配置
2. 用户认证状态管理
- Token管理:通过Cookie或LocalStorage保存认证令牌
- 用户信息:保持用户信息在应用生命周期内的同步
- 登出清理:确保登出时清除所有相关状态和缓存
3. 模块化设计原则
- 单一职责:每个模块只负责特定领域的状态
- 命名空间:避免不同模块间的状态冲突
- 状态隔离:模块间保持相对独立,通过明确接口交互
4. 异步操作处理
- API调用:在actions中处理异步请求
- 错误处理:统一的错误处理机制
- 状态同步:确保异步操作后的状态一致性
状态映射辅助函数
在组件中使用Vuex提供的辅助函数可以简化状态访问:
后台管理示例
import { mapState, mapGetters, mapMutations, mapActions } from \'vuex\';
export default {
computed: {
...mapState(\'admin\', [\'token\', \'userInfo\']),
...mapGetters([\'isLogin\'])
},
methods: {
...mapMutations([\'UPDATE_USERINFO\']),
...mapActions(\'admin/account\', [\'login\', \'logout\'])
}
}
移动端示例
import { mapState, mapGetters, mapMutations, mapActions } from \'vuex\';
export default {
computed: {
...mapState(\'app\', [\'token\', \'userInfo\']),
...mapGetters([\'isLogin\', \'cartNum\'])
},
methods: {
...mapMutations(\'app\', [\'LOGIN\', \'LOGOUT\']),
...mapActions(\'app\', [\'USERINFO\'])
}
}
注意事项
- 性能考虑:对于频繁变化的状态,注意避免不必要的重新渲染
- 内存管理:及时清理不需要的状态,防止内存泄漏
- 调试支持:开发环境下启用严格模式,便于调试状态变化
- 版本兼容:确保Vuex版本与Vue版本兼容
- 安全性:敏感信息(如token)的安全存储和传输
常见问题
1. 状态更新不生效
- 检查是否通过mutation修改状态
- 确认state对象是响应式的
2. 组件无法获取最新状态
- 检查mapState或computed计算属性的映射是否正确
- 确认状态更新是否正确触发了组件重渲染
3. 状态持久化失败
- 检查浏览器是否禁用了localStorage
- 确认缓存大小限制是否超出
4. 多模块状态同步问题
- 使用namespace避免命名冲突
- 通过dispatch调用其他模块的action进行跨模块通信
评论({{cateWiki.comment_num}})
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
{{cateWiki.page_view_num}}人看过该文档
评论(0)
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
16人看过该文档
{{item.user ? item.user.nickname : ''}}
(自评)
{{item.content}}
{{item.create_time}}
删除
搜索结果
为您找到{{wikiCount}}条结果
{{item.page_view_num}}
{{item.like ? item.like.like_num : 0}}
{{item.comment ? item.comment.comment_num : 0}}
位置:
{{path.name}}
{{(i+1) == item.catalogue.path_data.length ? '':'/'}}