“这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战”
阅读之前希望你有vuex的基础知识以及拥有一定的项目经验。
最近一年左右做一个视频在线编辑的项目,该项目是基于vue2.x的。项目中最复杂的页面是编辑页面,页面大概长这样(找了个类似的界面):
可以看到界面比较复杂,大大小小组件差不多几十个,如果不使用状态管理库的话,使用父子组件交互比较麻烦,所以最终选用了vuex作为状态管理的库。
那么像这种比较复杂的项目,vuex的代码将如何组织呢?下面是我推荐的方法:
首先一个项目会有很多模块(或者叫页面),我的建议是将store按照业务逻辑的模块进行划分,一个业务模块对应一个module
这里需要注意的是:
- 不要把所有的业务模块放到一个store里面,这样项目状态变多之后就不太好维护。
- 一个业务模块不要对应多个vuex的module,即使很复杂。
犯下的错(可以跳过)
这两个坑我都踩过,刚开始做项目的时候,项目比较小,也很简单,编辑页面也没有现在那么复杂,我大概看了一下,需要存的状态只有用户信息和编辑页面的一些状态,没多少,我就放一起了。代码大概这样,所有的状态都在store中
export const store = new Vuex.Store({
state: {
userInfo:{
id:'',
token:'',
phone:''
},
materials:[],
audio:[],
task:[]
},
mutations: {},
modules: {},
})
这样搞完之后,代码稳定运行了一段时间。 后来产品让加功能,支持多个视频场景,支持背景,支持滤镜,分辨率调整,素材动画等等乱七八糟的功能,需要存的状态也多了很多,都放到一起,store这个文件就太长了,达到了一千多行。在这种情况下,我感觉状态再加下去store那个文件会越来越不好维护,所以重构了下代码,这时我犯下了第二个错误:
我把编辑页面的状态分成了好几个module,大概长这样
const user={
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const material = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const audio = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
//...其他模块
const store = new Vuex.Store({
modules: {
user:user,
material: material,
audio: audio,
//其他模块
}
})
这样带来的问题是,代码太分散了,我一个编辑页面就对应了好几个module,太分散了维护也不好维护,也不够模块化。
最终结局方案
最终解决方案就是:一个单独的业务模块对应一个store的模块
我项目中涉及的业务模块有:用户模块,编辑模块,管理模块,工具包模块,假如每个模块都有需要存储的状态,就可以搞4个module
const store = new Vuex.Store({
modules: {
user,
edit,
manage,
toolkit
}
})
每个模块对应一个文件或者文件夹,有的模块状态比较简单,例如user,新建一个user.js
文件存放状态即可,对于复杂的模块,例如edit,就需要建立一个文件夹了。
目录如下:
vuex-demo/store
├── index.js
└── module
├── edit
│ ├── audio.js
│ ├── component.js
│ ├── edit-mutations.js
│ ├── edit.js
│ └── material.js
└── user.js
搞成一个文件夹(而不是一个文件)是为了不把所有的状态都写在edit.js
中,防止一个文件过大。在edit.js中使用拓展运算法又做了进一步的代码模块化,代码如下:
edit.js
代码如下:
import { audio } from './audio'
import {material} from './material'
export const edit = {
state: () => ({
...audio.state,
...material.state
}),
getters: {
...audio.getters,
...material.getters
},
mutations: {
...audio.mutation,
...material.mutation
},
actions: {
...audio.actions,
...material.actions
},
}
就这样,很简单哈。
说了那么多,大部分都是废话,有用的代码不过十几行,代码放在这里了传送门
vuex持久化插件推荐
我们存在vuex中的数据,尤其是用户数据,一刷新页面就无了,这和我们的预期不一样,好多人(尤其是年轻人)以为的状态管理库是可以持久保存的,即我刷新页面也还在。
之所以这样以为其实是对vuex的本质认知不够,vuex的本质就是一个JS大对象,保存在内存里,类似于下面
let store={state:{},getter:{}}
new Vue({ store: store})
你一刷新页面,内存中的数据肯定清空,所以store中的数据无了也是正常的。如果你要存起来,你可以选择vuex和localStorage或者sessionStorage或者cookie配合。 你需要
- 提交Mutation时,同时存到本地储存中(注意如果是对象的话需要JSON.stringify)
- 刷新页面时(可以在App.vue中的created方法中),从本地储存中取到用户信息,如果有的话提交一下Mutation
export const user = {
state: () => ({
info:{}
}),
getters: {},
mutation: {
setUser(state,info){//1. 提交Mutation时,同时存到本地储存中
localStorage.setItem('user',JSON.stringify(info))
state.info=info
}
},
actions: {},
}
created() {
const userInfo=localStorage.getItem('user')
if(userInfo){
// 提交Mutation,更新用户信息
}
}
这样存,你有一个数据你就存一次,有两个数据就存两次,有n个就存n次,太累了,所以推荐个插件, 在提交mutation时自动存,页面刷新时自动更新,方便的很。就不写demo了,累了。
插件地址 vuex-persistedstate
这一篇终于水完了,明天不知道写什么了,希望大家给点建议,评论区留言一下。
🐢