Vuex:Vue 的全局数据管理模式
store:仓库
Vuex 就是一个 Vue 项目所有数据的仓库,包括数据本身和对这些数据的处理,对外提供接口,外部只能调用接口,不能直接对仓库中的数据进行操作。
全局状态管理(全局数据管理)的好处:
- 解耦:将所有数据相关的逻辑放入 store(也就是 MVC 中的 Model)
- 数据读写更方便:任何组件不管在哪里,都可以直接读写数据
- 控制力更强:组件对数据的读写只能使用 store 提供的 API 进行,但无法阻止队友直接对数据进行操作
使用
在文件 store/index.ts 中 ```typescript import Vue from ‘vue’ import Vuex from ‘vuex’
Vue.use(Vuex)
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } })
在 Vue 实例中注入 store
```typescript
new Vue({
store, // 等同于 store: store
render: h => h(App)
}).$mount('#app')
可以在 Vue 项目中任意地方使用 this.$store 访问
this.$store.commit('increment')
console.log(this.$store.state.count) // -> 1
State
就是 Vue 里的 data 选项
为了使得数据是响应试的,获取 store 中的数据时应使用计算属性
computed: {
count () {
return this.$store.state.count;
}
}
// TS 中使用get
get count() {
return this.$store.state.count;
}
Getter
就是 Vue 里的 computed 选项
const store = 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);
},
doneTodosCount: (state, getters) => {
return getters.doneTodos.length;
},
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id);
}
}
})
访问
// 通过属性访问
this.$store.getters.doneTodos;
this.$store.getters.doneTodosCount;
// 通过方法访问
this.$store.getters.getTodoById(2);
Mutations
就是 Vue 里的 method 选项
没有返回值
只能接收两个参数,第二个可以为对象,可以传入多个值
mutations: {
increment (state, payload:{a:number, b:number}) {
state.count += payload.a;
}
}
使用:
this.$store.commit('increment', {
amount: 10
})
Actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态(就是回调)。
- Action 可以包含任意异步操作,mutation 必须同步执行。
使用:const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment1 (context) {
context.commit('increment');
},
// 可使用参数解构
increment2 ({ commit }) {
commit('increment');
},
// 可以在 action 内部执行异步操作
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000)
}
}
})
this.$store.dispatch('increment1');
Modules
当应用变得非常复杂时,store 对象就有可能变得相当臃肿
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割 ```typescript const moduleA = { state: () => ({ … }), mutations: { … }, actions: { … }, getters: { … } }
const moduleB = { state: () => ({ … }), mutations: { … }, actions: { … } }
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态 ``` 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。若要使用局部命名请看命名空间