vuex
vuex 集中式存储管理利用的所有组件的状态, 并以相应的规定保障状态以可预测的形式发生变化
应用 vuex
(1) 导入 vuex
vue add vuex
(2) 外围概念
state: 状态数据
mutations: 批改状态的函数
action: 异步操作
(3) 状态 store — 保留利用状态
export default new Vuex.store({
state: {counter: 0}
})
(4) mutation — 状态变更
export default new Vuex.store({
state: {counter: 0},
mutations: {add(state){state.counter++}
}
})
(5) getters — 从 state 中派生出的状态, 相似计算属性
export default new Vuex.store({
state: {counter: 0},
mutations: {add(state){state.counter++}
},
getters: {doubleCounter(state) {return state.counter * 2}
}
})
(6) actions — 增加业务逻辑
export default new Vuex.store({
state: {counter: 0},
mutations: {add(state){state.counter++}
},
actions: {add({commit}){setTimeout(()=>{commit('add');
},1000)
}
},
getters: {doubleCounter(state) {return state.counter * 2}
}
})
测试代码
<p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
<p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
<p>double:{{$store.getters.doubleCounter}}</p>
vuex 原理剖析
任务分析
-
实现插件
(1) 实现 store 类维持一个响应式的 store 实现 commit 实现 dispatch getters
(2) 挂载 $store
- 初始化 Store 申明, install 实现
let Vue;
class Store{constructor(options) {
// data 响应式解决
this._vm = new Vue({
data: {$$state: options.state}
})
}
get state(){return this._vm_data.$$state}
}
function install(_Vue) {
Vue = _Vue;
Vue.mixin({beforeCreated(){if (this.$options.store) {Vue.prototype.$store = this.$options.store}
}
})
}
export default {Store, install}
实现 commit 依据用户传入的 type 获取并执行对应的 mutations
class Store{constructor(options) {
// data 响应式解决
this._vm = new Vue({
data: {$$state: options.state}
})
// 保留用户配置的 mutations 选项
this._mutations = options._mutations || {};
this._actions = options._actions || {};}
get state(){return this._vm_data.$$state}
commit (type) {
// 获取 type 指定的 mutation
const entry = this._mutations[type];
if (!entry) {console.log('unknow mutation')
return
}
// 传递 state 给 mutation
entry(this.state);
}
dispatch (type) {
// 获取 type 指定的 mutation
const entry = this._mutations[type];
if (!entry) {console.log('unknow mutation')
return
}
// 传递 state 给 mutation
entry(this.state);
}
}
实现 dispatch 依据用户传入的 type 获取并执行对应的 actions
class Store{constructor(options) {
// data 响应式解决
this._vm = new Vue({
data: {$$state: options.state}
})
// 保留用户配置的 mutations 选项
this._mutations = options._mutations || {};
this._actions = options._actions || {};
// 须要异步解决上下文
this.dispatch = this.dispatch.bind(this);
}
get state(){return this._vm_data.$$state}
dispatch (type) {
// 获取 type 指定的 action
const entry = this._actions[type];
if (!entry) {console.log('unknow action')
return
}
// 传递 state 给 action
entry(this);
}
}
实现 getters
class Store{constructor(options) {
// data 响应式解决
this._vm = new Vue({
data: {$$state: options.state}
})
// 保留用户配置的 mutations 选项
this._mutations = options._mutations || {};
this._actions = options._actions || {};
// 须要异步解决上下文
this.dispatch = this.dispatch.bind(this);
this.getters = {};
Object.keys(options.getters).forEach(getterName => {
Object.defineProperty(this.getter, getterName, {get:()=>{return options.getters[getterName](this.state)
}
})
})
}
get state(){return this._vm_data.$$state}
}
残缺代码
// 1. 插件: 挂载 $store
// 2. 实现 Store
let Vue
class Store {constructor(options) {
// data 响应式解决
this._vm = new Vue({
data: {$$state: options.state}
})
this._mutations = options.mutations;
this._actions = options.actions;
this.commit = this.commit.bind(this);
this.dispatch = this.dispatch.bind(this);
// 实现 getters
this.getters = {};
Object.keys(options.getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {get: () => {return options.getters[getterName](this.state)
}
})
})
}
get state(){return this._vm._data.$$state}
commit(type, payload) {const entry = this._mutations[type];
if (!type) {console.log('unknow muyations type')
}
entry(this.state, payload)
}
dispatch(type, payload) {const entry = this._actions[type];
if (!type) {console.log('unknow action type')
}
entry(this, payload)
}
}
function install (_Vue) {
Vue = _Vue;
Vue.mixin({beforeCreate() {if (this.$options.store) {Vue.prototype.$store = this.$options.store;}
},
})
}
export default {Store, install};