持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天
vuex使用方法与规范
我们一般将所有需要管理的数据都存入到一个store对象中,更加方便后期管理(state单一状态树)
如果获取state中数据时,想要获取其变化后的值,需要在getters中进行操作(比如增减变化、数据过滤等等),调用时不用加括号,以属性的方式调用
getters: {
powerCounter(state) {
return state.counter * state.counter
},
//方法中还可以传入第二个参数,第二个参数就是getters本身,可以通过这个本身在getters方法中调用另一个getters方法
dulPowCounter(state, getters){
return getters.state * getters.state
},
//如果想在方法中传入自定义值,需要将返回值写为方法
customizePowCounter(state){
return (num) => {
return state.counter ** num;
}
}
}
//App.vue中使用方法
{{$store.getters.customizePowCounter(3)}}
mutations补充:
-
vuex的store状态的更新唯一方式就是提交Mutation,提交Mutation有两种方式:
- 第一种:
-
//这里sayHello是事件类型,后面的部分是回调函数,param2是第二个参数 sayHello(state, param2){ state.message += param2; } - 在App.vue中调用mutations中的方法时,如果想要传参,需要为commit提供后续参数:
-
$store.commit('sayHello', param2)//在methods中调用时,记得写成$store.commit()形式 - 传入的第二个参数被称为是mutation的载荷(Payload)
- 如果又很多个参数,则需要将多个参数以对象的形式封装传入
-
Mutation包含包括两部分:字符串的事件类型(type)和一个回调函数(handler)
- 我们就可以利用这两部分,进行另一种特殊的提交封装:
- 第二种:
-
//app.vue的methods中 sayHello(param2) { this.$store.commit({ type: 'incrementCount', param2 }) } - 这种方式传输过去的第二个参数是以对象形式传递的,需要用如下方式获取:
-
sayHello(state, param2){ state.message += param2.param2; } - 当然,这里的param2更建议写成payload
-
注:如果是在mutations的方法中为对象添加新的属性,则新的属性不在vuex的监听范围内,不能实现响应式(和数组中直接通过下标修改数组元素类似),如果是删除属性,delete操作符也同样不在监听范围内
- 如果要添加属性,可以用set方法:
-
Vue.set(state.info, 'address', 'los') - 如果要删除属性,可以用delete方法:
-
Vue.delete(state.info, 'age')
-
方法变量抽离写法:在mutations中定义方法并使用时,方法名(type)容易写错,官方建议我们将其抽离,具体做法如下:
- 在store文件夹下创建mutations-types.js文件,在其中定义方法名,导出后在App.vue和index.js中导入并引用:
-
//mutations-types.js export const SAYHELLO = 'sayHello' //App.vue import {SAYHELLO} from './store/mutations-type.js'//或者用*全部导入 methods: { sayHello(){ this.$store.commit(SAYHELLO) } } //mutations中(记得在index.js的头部引入常量) mutations: { [SAYHELLO](state){ state.message += param2.param2; } }
vuex-action的使用
通常情况下,Vuex要求我们Mutation中的方法必须是同步方法,主要原因是当我们使用devtools时,devtools可以帮助我们捕捉mutation的快照,但如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候会被完成
这时候我们就要用到actionl来处理异步操作:
-
在actions中定义方法,将异步操作放入:
actions: { //这里要传入context对象 actionsTimeOut(context){ setTimeout(() => { context.commit('mutationTimeOut') },1000) } }, -
mutations中做异步后的同步操作:
mutations: { mutationTimeOut(state){ //dosth } }, -
App.vue中将操作分发至actions:
methods: { timeOut(){ //使用dispatch分发至actions this.$store.dispatch('actionTimeOut') } }注:actions中也可使用payload,为第二个参数
想要在异步操作完成后对外界调用处进行通知,有两种方式:
第一种:dispatch时传入一个回调函数,在actions中commit下一行调用该回调函数,以起到通知的效果
第二种(推荐):在action的方法中返回Promise,在commit操作后调用resolve方法,回到methods中,在dispatch分发后紧接着调用then方法
//App.vue
methods: {
timeOut(){
//使用dispatch分发至actions
this.$store.dispatch('actionsTimeOut').then(mes => console.log(mes))
}
}
//store/index.js
actions: {
//这里要传入context对象,也可以利用解构写成如下形式:
actionsTimeOut({commit}){
return new Promise((resolve, rejeck) => {
setTimeout(() => {
context.commit('mutationTimeOut')
resolve('done');
},1000);
})
}
},
getters: {
mutationTimeOut(state){
//dosth
}
},
Vuex-Module的使用
Vue使用单一状态树,意味着很多状态(变量)都要交给Vuex来管理,当应用变得非常复杂时,store对象就会变得相当臃肿,为了解决这个问题,Vuex允许我们将store分割成模块,而每个模块允许拥有自己的state、mutations、actions、getters等等
//定义moduleA
const modulaA = {
state: {
name: 'zhangsan'
},
mutations: {
fun(){
//dosth
}
}
}
//引入moduleA
modules: {
a: modulaA
}
//App.vue中的引用
//state中状态要记得.模块名
//mutations中的方法不需要.模块名,在子模块中找不到会自动去父模块中去找
{{$store.state.a.name}}
$store.commit('fun')
//调用getters中方法与mutations中类似,同样不需要.模块名,但注意以下情况
//子模块getter中访问父模块state属性
getter: {
fun(state, getters, rootState){
//通过rootState.pamas的方式获取
}
}
//actions中方法的context对象不包括父模块,这也意味着commit只能针对自己所在模块的mutations
//要用action访问父模块的state,使用rootState.paramname
store项目结构
-
store
-
index.js //组装模块并导出store的地方,state就放在这里
-
actions.js //根级别的action
-
mutations.js //根级别的mutation
-
modules
- modulesA.js //A模块部分
- modulesB.js //B模块部分
-