Vuex
Vuex 集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。
核心概念
state 状态、数据 mutations 更改状态的函数 actions 异步操作
store 包含以上概念的容器
状态 - state
state保存应用状态
export default new Vuex.Store({
state: { counter:0 },
})
状态变更 - mutations
mutations用于修改状态,store.js
export default new Vuex.Store({
mutations: {
add(state) {
state.counter++
} }
})
派生状态 - getters
从state派生出新状态,类似计算属性
export default new Vuex.Store({
getters: {
doubleCounter(state) { // 计算剩余数量 return state.counter * 2;
} }
})
动作 - actions
添加业务逻辑,类似于controller
export default new Vuex.Store({
actions: {
add({ commit }) {
setTimeout(() => {
commit('add')
}, 1000);
} }
})
vuex原理解析
任务分析
实现一个插件:声明Store类,挂载$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实例
// 传递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 {commit, action} = store
this.commit = function boundCommit(type, payload) {
commit.call(store, type, payload)
}
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);
}
}
实现getter,state的计算属性
let Vue;
class Store {
constructor(options) {
// 定义响应式的state
// this.$store.state.xx
// 借鸡生蛋
let computed={}
Object.keys(options.getters).forEach(function (key) {
computed[key]=function () {
return options.getters[key](options.state)
}
})
console.log(computed)
this._vm = new Vue({
data: {
$$state: options.state
},
computed:computed
})
this._mutations = options.mutations
this._actions = options.actions
// 绑定this指向
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
get getters() {
return this._vm
}
// 只读
get state() {
return this._vm._data.$$state
}
set state(val) {
console.error('不能直接赋值呀,请换别的方式!!天王盖地虎!!');
}
// 实现commit方法,可以修改state
commit(type, payload) {
// 拿出mutations中的处理函数执行它
const entry = this._mutations[type]
if (!entry) {
console.error('未知mutaion类型');
return
}
entry(this.state, payload)
}
dispatch(type, payload) {
const entry = this._actions[type]
if (!entry) {
console.error('未知action类型');
return
}
// 上下文可以传递当前store实例进去即可
entry(this, payload)
}
}
function install(_Vue){
Vue = _Vue
// 混入store实例
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
// { Store, install }相当于Vuex
// 它必须实现install方法
export default { Store, install }
网友评论