vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
在《快速入门(一)》中我们提到过,我们可以把 Vuex 简单的抽象为,一个全局对象(store),里面保存了所有组件公有的状态(state)。只是这个全局对象不能直接读写。需要通过特殊的读写渠道。在 vuex 中写渠道需要用户自定义,分为 Mutations
同步设置,和 Actions
异步设置
Vuex 声明及注入
Vue.use(Vuex);export default new Vuex.Store({ state, getters, mutations, actions, modules})
根组件中调用
import store form './store'new Vue({ el: '#app', router, store, template: '', components: { App }})
以上我们完成了,Vuex 的申明及注入 Vue 中。现在我们先来看看在申明 Vuex.Store 中,各项所代表的意思。
State
用以保存仓库 Store 中根状态。格式如下:
export default { token: null, // 用户本地登录凭证, newCredit:false, loading: { show: false, msg: '' }, dialogMsg: { msgShow: false, msg: '', timeout: null }}
你没有看错,就是一个简单的对象。这些就是我们整个项目需要共享的状态(state)。
Mutations
如果我们需要修改 state 中的状态,就需要借助 Mutations。Mutations 为我们提供了同步修改 state 的方法。
import { SHOW_LOADING, HIDE_LOADING, SHOW_NEW_CREDIT, HIDE_NEW_CREDIT,} from './mutationTypes'export default { [SHOW_LOADING](state,msg){ state.loading = { show:true, msg } }, [HIDE_LOADING](state){ state.loading = Object.assign(state.loading, {show:false}); }, [SHOW_NEW_CREDIT](state){ state.newCredit = true; }, [HIDE_NEW_CREDIT](state){ state.newCredit = false; }}
从上面的实例,我们发现,Mutations 由一个个函数组成,函数的第一个参数为 state 。指向上面我们申明的 State 对象。第二个参数为新值。函数内执行一个同步的赋值过程。然后函数名有点怪,是为了方便管理 Mutations 函数,我们让函数名由一个独立的文件提供(这个都是小问题)。
Actions
Actions 和 Mutations 结构一样,都提供一些函数,不一样的是,Actions 主要为异步修改 State 而生。
import { SET_DIALOG_MSG, SET_DIALOG_MSG_SHOW, SET_DIALOG_MSG_TIMEOUT} from './mutationTypes'export default { setDialogMsg({commit, state},msg){ commit(SET_DIALOG_MSG,msg); commit(SET_DIALOG_MSG_SHOW,true); if(state.dialogMsg.timeout){ clearTimeout(state.dialogMsg.timeout); } commit(SET_DIALOG_MSG_TIMEOUT,setTimeout(() =>{ // this.msg = ''; commit(SET_DIALOG_MSG_SHOW,false); },1500)) }}
Actions 函数也接受两个参数,第二个参数与 Mutations 函数一样,都是 state 新值。第一个参数是一个 content 对象,其中可以包含 commit 函数和 state 对象。前者是拿来帮助我们触发 Mutations 的,后则是仅供我们读取 state 中的数据
我们发现最后修改 State 状态的其实还是 Mutations 函数,Actions 只是异步去调用而已。
Getters
Getters 是 State 的补充,当我们需要从 State 中派生出某些值时,而且多个组件同时都需要使用此派生时,我们可以把这个派生提取到 Getters 中。
export default{doneTodos: state => { return state.todos.filter(todo => todo.done) }doneTodosCount: (state, getters) => { return getters.doneTodos.length }}
Modules
目前我们介绍的共享状态都是直接保存在根状态树中的(state),这样务必会导致 state 变得很臃肿 。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
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 的状态
Store 的使用
上面我们介绍了,申明 Store 时 State、Mutations、Actions、Getters 的作用。现在我们来看看,在 Vue 项目中,如何引用这些状态或方法。
mapState 辅助函数
帮助我们把全局共享状态,引入到局部组件中。
// 在单独构建的版本中辅助函数为 Vuex.mapStateimport { mapState } from 'vuex'export default { // ... computed: { ...mapState({ // 箭头函数可使代码更简练 count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } // 获取 loan 模块中的状态。 loanMoney:state => state.loan.money }) }}
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
computed: { ...mapState([ // 映射 this.count 为 store.state.count 'count' ])}
mapGetters 辅助函数。
使用方法同 mapState。
mapMutations 辅助函数
你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
import { mapMutations } from 'vuex'export default { // ... methods: { ...mapMutations([ 'increment' // 映射 this.increment() 为 this.$store.commit('increment') ]), ...mapMutations({ add: 'increment' // 映射 this.add() 为 this.$store.commit('increment') }) }}
注意,对于 mutations 是不区分根 state 中的 mutations 还是 module 中的 mutations 都是一样的引入方式。
mapActions 辅助函数
使用方法同 mapMutations
参考文档: