Step01.命名一個storeService要一個只讀state
var storeService = new Object({ _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') } });
Step02.建立一些列mutation改變state
var storeService = new Object({ _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') }, mutationModifyAge(newAge) { state.age = newAge; }, mutationModifyAge2(newAge) { state.age = newAge; }, mutationModifyAge3(newAge) { state.age = newAge; } });
Step03.須要一個watch監聽改變,每一次改變狀態的時候(執行mutation)調用listenCallback 返回狀態
var storeService = new Object({ _listeners: [], _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') }, mutationModifyAge(newAge) { state.age = newAge; this._dealCallback(); }, mutationModifyAge2(newAge) { state.age = newAge; this._dealCallback(); }, mutationModifyAge3(newAge) { state.age = newAge; this._dealCallback(); }, _dealCallback() { this._listeners.forEach(listener => listener(this.state)) }, watch(listener) { // 優化想要第一次監聽的時候返回當前狀態 listener(this.state); this._listeners.push(listener); } }); // 監聽store storeService.watch(function (state) { console.log('callback', state); }) // 改變狀態 storeService.mutationModifyAge(2)
Step04.統一使用dispatch調用mutation法
var storeService = new Object({ _listeners: [], _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') }, dispatch(type, ...paylod) { // 打印日誌信息 console.log(type ? type : '監聽', '改變以前的狀態', this.state); if (this._mutation[type]) { this._mutation[type](this.state, ...paylod); } console.log(type ? type : '監聽', '改變以後的狀態', this.state); // 能夠少寫好多個listenCallback this._dealCallback(); }, _mutation: { mutationModifyAge(state, newAge) { state.age = newAge; }, mutationModifyAge2(state, newAge) { state.age = newAge; }, mutationModifyAge3(state, newAge) { state.age = newAge; } }, _dealCallback() { this._listeners.forEach(listener => listener(this.state)) }, watch(listener) { // 優化想要第一次監聽的時候返回當前狀態 // listener(this.state); // 優化讓第一次監聽也能夠記錄歷史日誌 this.dispatch(); this._listeners.push(listener); } }); // 監聽store storeService.watch(function (state) { console.log('callback', state); }) // 改變狀態 storeService.dispatch('mutationModifyAge', 2)
以上內容爲建立一個簡單的store。
如下開始按照Vuex0.3.0開始優化
Step05.vuex dispatcher調用的方法是mutation,
mutation是惟一操做state的方法,
mutation不可包含任何反作用,
mutation對外暴露dispatch調用將上面的mutation 改成mutation
var storeService = new Object({ _listeners: [], _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') }, dispatch(type, ...paylod) { // 打印日誌信息 console.log(type ? type : '監聽', '改變以前的狀態', this.state); if (this._mutation[type]) { this._mutation[type](this.state, ...paylod); } console.log(type ? type : '監聽', '改變以後的狀態', this.state); // 能夠少寫好多個listenCallback this._dealCallback(); }, _mutation: { mutationModifyAge(state, newAge) { state.age = newAge; }, mutationModifyAge2(state, newAge) { state.age = newAge; }, mutationModifyAge3(state, newAge) { state.age = newAge; } }, _dealCallback() { this._listeners.forEach(listener => listener(this.state)) }, watch(listener) { // 優化想要第一次監聽的時候返回當前狀態 // listener(this.state); // 優化讓第一次監聽也能夠記錄歷史日誌 this.dispatch(); this._listeners.push(listener); } }); // 監聽store storeService.watch(function (state) { console.log('callback', state); }) // 改變狀態 storeService.dispatch('mutationModifyAge', 2)
Step05.vuex中mutation爲純函數,不可包含任何反作用,添加action來處理一系列反作用,最終仍是調用dispatch 去改變state
var storeService = new Object({ _listeners: [], _state: { age: 1 }, get state() { return this._state; }, set state(v) { throw new Error(' is read only.') }, dispatch(type, ...paylod) { // 打印日誌信息 console.log(type ? type : '監聽', '改變以前的狀態', this.state); if (this._mutation[type]) { this._mutation[type](this.state, ...paylod); } console.log(type ? type : '監聽', '改變以後的狀態', this.state); // 能夠少寫好多個listenCallback this._dealCallback(); }, _mutation: { mutationModifyAge(state, newAge) { state.age = newAge; }, mutationModifyAge2(state, newAge) { state.age = newAge; }, mutationModifyAge3(state, newAge) { state.age = newAge; } }, _dealCallback() { this._listeners.forEach(listener => listener(this.state)) }, watch(listener) { // 優化想要第一次監聽的時候返回當前狀態 // listener(this.state); // 優化讓第一次監聽也能夠記錄歷史日誌 this.dispatch(); this._listeners.push(listener); }, bindAction(actions) { this.actions = Object.create(null); this._actions = Object.create(null); function createAction(action, store) { if (typeof action === 'function') { return (...payload) => action(store, ...payload) } } Object.keys(actions).forEach(name => { console.log(actions[name]); this._actions[name] = createAction(actions[name], this) if (!this.actions[name]) { this.actions[name] = (...args) => this._actions[name](...args) } }) } }); var actions = { // 包含反作用的action asyncModifyAge(store, ...paylod) { setTimeout(() => { store.dispatch('mutationModifyAge', ...paylod) }, 2000); }, // 屢次調用dispatch asyncMulModifyAge(store, ...paylod) { setTimeout(() => { store.dispatch('mutationModifyAge', ...paylod) }, 2000); store.dispatch('mutationModifyAge2', ...paylod) } } storeService.bindAction(actions); // 監聽store storeService.watch(function (state) { console.log('callback', state); }) // 改變狀態 storeService.dispatch('mutationModifyAge', 2) storeService.actions.asyncMulModifyAge(21);
Step06 封裝成一個類hKeeper
var defaultOption = { state: {}, actions: {}, mutations: {} }; class hKeeper { constructor(options) { options = Object.assign({}, defaultOption, options); this._state = options.state; this.listeners = []; const dispatch = this.dispatch; this.dispatch = (...args) => { dispatch.apply(this, args); }; this.actions = Object.create(null); this._setupMutations(options.mutations); this._setupActions(options.actions); } get state() { return this._state } set state(v) { throw new Error('[hKeeper] hKeeper state is read only.') } dispatch(type, ...payload) { const mutation = this._mutations[type] const state = this.state if (mutation) { mutation(state, ...payload) } this.listeners.forEach(listener => listener(this.state)) } _setupMutations(mutations) { this._mutations = mutations; } // 設置action _setupActions(actions) { function createAction(action, store) { if (typeof action === 'function') { return (...payload) => action(store, ...payload) } } this._actions = Object.create(null) Object.keys(actions).forEach(name => { this._actions[name] = createAction(actions[name], this) if (!this.actions[name]) { this.actions[name] = (...args) => this._actions[name](...args) } }) } watch(listener) { listener(this.state); this.listeners.push(listener) } } var storeService = new hKeeper( { state: { age: 1 }, actions: { // 包含反作用的action asyncModifyAge(store, ...paylod) { setTimeout(() => { store.dispatch('mutationModifyAge', ...paylod) }, 2000); }, // 屢次調用dispatch asyncMulModifyAge(store, ...paylod) { setTimeout(() => { store.dispatch('mutationModifyAge', ...paylod) }, 2000); store.dispatch('mutationModifyAge2', ...paylod) } }, mutations: { mutationModifyAge(state, newAge) { state.age = newAge; }, mutationModifyAge2(state, newAge) { state.age = newAge; }, mutationModifyAge3(state, newAge) { state.age = newAge; } } } ) // 監聽store storeService.watch(function (state) { console.log('callback', state); }) // 改變狀態 storeService.dispatch('mutationModifyAge', 2) storeService.actions.asyncMulModifyAge(21);
參考Vuex0.3.0版本 applyMiddleware 參考Redux
https://github.com/HereSincer...