Vuex集中式状态管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化
一.安装
vue add vuex
二.核心概念
- state 状态、数据
// 保存应用状态
export default new Vuex.Store({
state: { counter:0 },
})
- mutations更改状态的函数
// mutations用于修改状态
export default new Vuex.Store({
mutations: {
add(state) {
state.counter++
} }
})
- actions 异步操作
// 添加业务逻辑,类似于controlle
export default new Vuex.Store({
actions: {
add({ commit }) {
setTimeout(() => {
} }
})
- store是包含以上概念的容器
三.vuex原理解析
需求分析
- 实现一个插件:声明Store类,挂载$store
- 创建响应式的state,保存mutations、actions和getters
- 实现commit根据用户传入type执行对应mutation
- 实现dispatch根据用户传入type执行对应action,同时传递上下文
- 实现getters,按照getters定义对state做派生
源码实现
步骤一:初始化:Store声明、install实现
let Vue;
class Store {
constructor(options = {}) {
this._vm = new Vue({
data: {
?state:options.state
}
});
}
get state() {
return this._vm._data.?state
}
set state(v) {
console.error('please use replaceState to reset state');
} }
function install(_Vue) {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
} }
}); }
export default { Store, install };
步骤二: 实现commit:根据用户传入type获取并执行对应mutation
class Store {
constructor(options = {}) {
// 保存用户配置的mutations选项
this._mutations = options.mutations || {}
}
commit(type, payload) {
// 获取type对应的mutation
const entry = this._mutations[type]
if (!entry) {
console.error(`unknown mutation type: ${type}`);
return
}
// 指定上下文为Store实例
const store = this
const {commit} = store
this.commit = function boundCommit(type, payload) {
commit.call(store, type, payload)
}
// 传递state给mutation
entry(this.state, payload);
}
}
步骤三: 实现actions:根据用户传入type获取并执行对应action
class Store {
constructor(options = {}) {
// 保存用户编写的actions选项
this._actions = options.actions || {}
// 绑定commit上下文否则action中调用commit时可能出问题!!
// 同时也把action绑了,因为action可以互调
const store = this
const {action} = store
this.action = function boundAction(type, payload) {
return action.call(store, type, payload)
}
}
dispatch(type, payload) {
// 获取用户编写的type对应的action const entry = this._actions[type]
if (!entry) {
console.error(`unknown action type: ${type}`);
return
}
// 异步结果处理常常需要返回Promise
return entry(this, payload);
}
}
步骤四: 实现getters,根据用户传入的方法名称执行
class Store {
constructor(options = {}) {
// 保存用户编写的getters选项
this._wrappedGetters = options.getters || {}
// 定义computed选项
const computed = {}
// 给用户暴露一个可以访问的getters
this.getters = {}
// 绑定this指向
const store = this
// 遍历getters
Object.keys(this._wrappedGetters).forEach( key => {
// 获取用户定义的getter
const fn = store._wrappedGetters[key]
// 转化为computed可以使用的无参数的形式
computed[key] = function() {
return fn(store.state)
}
// 为getters定义只读属性
Object.defineProperty(store.getters, key, {
get: () => store.$vm[key]
})
})
this._vm = new Vue({
data: {
?state:options.state
},
computed
});
}
}