一、Vuex的核心模块
1. state
state状态,作用是用来存储 全局 的状态,目的是方便每个组件之间的通信,从而做到数据的统一管理。
2. getters
getters和vue中的computed计算属性是跟相似,都是对数据进一步加工/过滤,从而得到最终结果。
3. mutations
mutations的目的是做数据的同步赋值,官方推荐使用该方法进行同步赋值,而不推荐直接使用 $store.state.xx = xx。个人的看法,如果直接赋值的化,看似可以直接赋值成功,存在一些缺陷,我们没办法在赋值的基础上做其他的扩展,比如我不单单需要赋值,我要求在赋值的时候同时保存所有的赋值记录,方便调试工具的调试,那么此时使用mutations的优点便可以体现出来。
4. actions
actions的目的是用来做数据的异步赋值,可以在actions中调用mutations来赋值。
5. modules
modules的目的是用来做模块的划分,当项目过于复杂的时候,我们就可以使用modules来进行管理。
二、Store类
let Vue;
class Store {
constructor(opts) {
this._state = new Vue({
data: {
state: opts.state
}
});
let getters = opts.getters;
this.getters = {};
Object.keys(getters).forEach((val)=>{
Object.defineProperty(this.getters, val, {
get:()=>{
return getters[val](this.state);
}
})
})
let mutations = opts.mutations;
this.mutations = {};
Object.keys(mutations).forEach((val)=>{
this.mutations[val] = mutations[val];
})
let actions = opts.actions;
this.actions = {};
Object.keys(actions).forEach((val)=>{
this.actions[val] = actions[val];
})
}
get state() {
return this._state.state;
}
commit = (funName, params)=>{
// 在mutations中找到funName中对应的函数并且执行
this.mutations[funName](this.state, params);
}
dispatch(funName, params) {
this.actions[funName](this, params);
}
}
const install = (vue) =>{
Vue = vue;
vue.mixin({
beforeCreate() {
// 将store挂载到唯一的根组件上
if(this.$options && this.$options.store) {
this.$store = this.$options.store;
} else {
this.$store = this.$parent && this.$parent.$store;
}
},
})
}
export default {
Store,
install
}
分析:
- 我们需要一个给Vue.use方法提供一个install方法,用来做Vuex的安装,即目的是用来将store挂载到Vue的根组件上,从而达到Vuex的全局使用。
- 使用Vue.mixin全局混入方法,将每个组件的$store指向根组件。
- commit和dispatch是用来触发mutations和actions的方法,基本的原理就是发布订阅,需要特别数以一点this的指向问题。
- 我们发现this._state是Vue的实例对象,为什么要这样做?原因很简单,因为Vuex是一个响应式的插件,我们需要结合Vue来实现响应式原理,二Vue实例的对象具有响应式的功能,从而可以满足Vuex的响应式原理,达到页面和数据的同步更新。