不同层级的菜单分别占用一个 `state`,至于 `mutations`,本例中不同 `state` 分别对应写了一个 `mutations`,实际工作中为了更大成都减少代码复用,对于 menu 的状态管理可以只写一个 `mutations`,通过传参判断是更改哪个层级及对应的 menu。
需要注意的是 vuex 在页面刷新后状态会重新初始化,这显然和管理菜单所需功能不符(除了主动触发,其他操作不能对菜单产生影响)。可以通过vuex-persistedstate 改变 vuex 默认生命周期,下面示例代码将 vuex 状态存储在了 cookie 中:
js
const store = new Vuex.Store({
state: {
// 初始化
activeFirstMenu: 'firstMenu1',
activeSecondMenu : 'secondMenu1',
},
mutations: {
// 更改一级菜单
changeFirstActiveMenu (state, menu) {
state.activeFirstMenu = menu;
},
// 更改二级二级菜单
changeSecondActiveMenu (state, menu) {
state.activeSecondMenu = menu;
}
},
});
组件中渲染
在 template 动态加载高亮 class,通过 vuex 中 state 控制:
<div class="subMenu">
<span :class="{ activeSecondMenu: activeMenu.secondMenu1 }" @click="menuClicked('secondMenu1')">secondMenu1</span>
</div>
<div class="subMenu">
<span :class="{ activeSecondMenu: activeMenu.secondMenu2 }" @click="menuClicked('secondMenu2')">secondMenu2</span>
</div>
<div class="subMenu">
<span :class="{ activeSecondMenu: activeMenu.secondMenu3 }" @click="menuClicked('secondMenu3')">secondMenu3</span>
</div>
写 js 时有个技巧:路由 path 和对应高亮的 menu 名称最好相同,因为路由跳转和高亮 menu 直接相关,这样可以减少一个参数:
data () {
return {
// 初始化
activeMenu: {
// menu 名称相同,和对应路由的 path 相同
secondMenu1: '',
secondMenu2: '',
secondMenu3: '',
},
};
},
computed: {
activeMenuName () {
// 检测 vuex 中 activeSecondMenu 的变化
return this.$store.state.activeSecondMenu;
}
},
methods: {
menuClicked(path) {
// 取消当前 tab 高亮
this.activeMenu[this.activeMenuName] = false;
// 更新 vuex 状态及 menu 高亮
this.$store.commit("changeSecondActiveMenu", path);
this.activeMenu[this.activeMenuName] = true;
// 路由跳转 path 和对应 menu 名称相同
this.$router.push(`/somePath/${path}`);
},
init () {
// 刷新页面重置正确高亮菜单tab
this.activeMenu[this.activeMenuName] = true;
},
},
mounted: {
this.init();
},
其他
对于 vuex 的优化
上文有谈到,实际工作中为了更大程度实现代码复用,对于某个类别的状态管理可以只写一个 mutations ,通过传参(Payload )判断更改内容。还是以 menu 管理为例,可进行下面的优化:
