前言
学习vuex
之前,我提出了3个疑问。Vuex 官网
vuex
是什么?
官方文档解释:vuex
是一个专为 Vue.js 应用程序开发的状态管理模式
。
通俗点讲就是把这个项目中需要多个地方或全局使用的状态集中管理起来。
- 【Vuex|Vuex 学习笔记】
vuex
应用场景是什么?
举个栗子
①多个组件依赖一种状态。就是说这个状态一改变,其他依赖这个状态的组件都要跟着改变。如果是兄弟组件,使用传值的方式的话就比较麻烦。
②多个组件共用同一个请求的数据。我比较懒,又不想在多个组件写相同的请求,而且增加重复代码,怎么办?这时候vuex
就派上用场了。
从以上两个栗子得出:需要集中管理共同状态的都可以使用vuex
(不要滥用)
vuex
怎么用?
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.store({
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... },
modules: { ... }
})
// index.js
import Vue from 'vue';
import store from '/store';
new Vue({
// 全局挂载 Vuex
store
})
在真正使用之前,你要了解
vuex
扩展的几个核心概念。Vuex 核心概念 第一次看官方文档的时候,对下面几个概念不是很理解,认真看文档,换个理解方式就好多了。
-
state
:管理状态的地方;可以类比成vue
里面的data
。
注意:state(状态) 不能像 data 的属性那样通过赋值改变,只能通过 mutations 改变,这样的目的是为了更好地追踪状态的变化
export default new Vuex.Store({
state: {
count: 1,
...
}
})
-
mutations
:改变state
(状态)的地方;可以类比成vue
里面的methods
。
mutations
里面所有回调函数
接受的第一个参数是state
,其余参数是commit
传的。
注意:mutations 是同步触发的,无法监听回调函数中进行的状态的改变;那我要写异步请求改变状态怎么办,actions 才是干这事的。
export default new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 改变状态;也就是修改 state 里面 count 的值
state.count++
}
}
})
那怎么调用
mutations
的方法
改变state
?通过commit
(提交)的方式。// ...
mutations: {
increment (state, n) {
state.count += n
},
increment1 (state, params) {
state.count += params.amount
}
}
// ***.vue
// 普通方式提交
this.$store.commit('increment', 10)
// 以对象形式提交
this.$store.commit({
type: 'increment1',
amount: 10
})
-
actions
:类似于mutation
,但不同的是①actions
提交的是mutation
,而不是直接改变state
; ②actions
可以包含任意异步操作。
actions
接受的第一个参数是Store
实例具有相同方法和属性的context
对象,其余参数是dispatch
分发的
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync(context) {
context.commit('increment')
},
// 参数解构
incrementAsync1 ({ commit, getters }, params) {
commit('increment')
},
// 回调方式提交
incrementAsync2 ({ commit, getters }, params) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
})
那怎么调用
actions
的方法? 通过dispatch
(分发)的方式。// 以普通方式分发
this.$store.dispatch('incrementAsync')// 以载荷形式分发
this.$store.dispatch('incrementAsync1', {
amount: 10
})// 以对象形式分发
this.$store.dispatch({
type: 'incrementAsync2',
amount: 10
})
-
getters
:可以看做是Store
实例的计算属性;用法与vue
的计算属性一致。
getters
的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
getters
只接受两个参数state
、getters
。要是实现给getter
传参,只能通过让getter
返回一个函数。
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// 接收两个参数
doneTodos1: (state, getters) => {
return getters.doneTodos.length
},
// 返回一个函数
doneTodos2: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
})
调用
getters
注意:getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
// 通过属性调用
this.$store.getters.doneTodos1
// 通过方法调用
this.$store.getters.doneTodos2(1)
-
modules
:模块的意思;每个模块拥有自己的state
、mutation
、actions
、getters
、甚至是嵌套子模块。
当项目非常复杂时候,将Store
分割成多个module
(模块)管理的话维护起来就方便多了。
// ...
export default new Vuex.Store({
modules: {
moduleA,
moduleB
}
})
总结
- 如果认真看完就会发现与官网给的核心概念的目录顺序不同,我建议看文档的顺序是先看
state
、mutation
、actions
,然后再看getters
、modules
,这样相对容易理解。 - 详情请移步 Vuex 官网