隨著React和Vue等非同步框架的廣泛運用,前端狀態管理器逐漸成為前端開發比不可少話題。形如React有倍受歡迎的Redux,再如Vue標配的狀態管理器Vuex,都是業內相對成熟的狀態管理器,那麼我們接下來就用原生javascript來實現一個狀態管理器。
主要包含兩個方面:第一是釋出訂閱,第二是狀態管理。
首先我們先建立一個PubSub類函數:
class PubSub { constructor() { // 收集事件 this.events = {}; } }複製程式碼
接著我們來實現一個釋出函數:
class PubSub { ... // 釋出 publish(event, data = {}) { const self = this; /* * 校驗是否存在事件 * 預設返回一個空陣列 */ if (!self.events.hasOwnProperty(event)) { return []; } // 遍歷執行事件佇列裡的回撥函數 return self.events[event].map((callback) => callback(data)); } ... }複製程式碼
實現完釋出函數publish,接著我們來實現訂閱函數:
class PubSub { ... // 訂閱 subscribe(event, callback) { const self = this; /* * 校驗是否存在事件 * 預設給一個空陣列 */ if (!self.events.hasOwnProperty(event)) { self.events[event] = []; } // 將事件推入回撥佇列 return self.events[event].push(callback); } ... }複製程式碼
class PubSub { constructor() { // 收集事件 this.events = {}; } // 訂閱 subscribe(event, callback) { const self = this; /* * 校驗是否存在事件 * 預設給一個空陣列 */ if (!self.events.hasOwnProperty(event)) { self.events[event] = []; } // 將事件推入回撥佇列 return self.events[event].push(callback); } // 釋出 publish(event, data = {}) { const self = this; /* * 校驗是否存在事件 * 預設返回一個空陣列 */ if (!self.events.hasOwnProperty(event)) { return []; } // 遍歷執行事件佇列裡的回撥函數 return self.events[event].map((callback) => callback(data)); } }複製程式碼
首先我們建立一個Store類函數:
class Store { // 傳入params物件 constructor(params) { const self = this; self.actions = {}; // 非同步任務物件 self.mutations = {}; // 同步任務物件 self.state = {}; // 全域性狀態物件 self.plugins = []; // 外掛 self.status = "resting"; // 初始狀態 /* * 初始化設定actions物件 * 該物件主要處理非同步事件 */ if (params.hasOwnProperty("actions")) { self.actions = params.actions; } /* * 初始化設定mutations物件 * 該物件主要處理同步事件 */ if (params.hasOwnProperty("mutations")) { self.mutations = params.mutations; } // 外掛 if (params.hasOwnProperty("plugins")) { self.plugins = params.plugins; } /* * 代理監聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設定state物件並賦值 state[key] = value; // 更改狀態 self.status = "resting"; return true; }, }); } }複製程式碼
接著我們來實現核心函數commit,該函數主要處理物件更改,呼叫mutations物件內的函數:
class Store { ... commit = (mutationKey, payload) => { const self = this; // 校驗是否存在函數 if (typeof self.mutations[mutationKey] !== "function") { console.warn(`Mutation ${mutationKey} dose not exist`); return false; } // 變更狀態 self.status = "mutation"; // 執行對應函數 self.mutations[mutationKey](self.state, payload); return true; }; ... }複製程式碼
實現完commit,我們再來實現dispatch,這個函數主要處理非同步問題,傳入commit方法:
class Store { ... dispatch = (actionKey, payload) => { const self = this; // 校驗是否存在函數 if (typeof self.actions[actionKey] !== "function") { console.warn(`Action ${actionKey} dose not exist`); return false; } // 變更狀態 self.status = "action"; // 執行對應函數,並傳入commit self.actions[actionKey]({ commit: self.commit }, payload); return true; }; ... }複製程式碼
class Store { // 傳入params物件 constructor(params) { const self = this; self.actions = {}; // 非同步任務物件 self.mutations = {}; // 同步任務物件 self.state = {}; // 全域性狀態物件 self.plugins = []; // 外掛 self.status = "resting"; // 初始狀態 /* * 初始化設定actions物件 * 該物件主要處理非同步事件 */ if (params.hasOwnProperty("actions")) { self.actions = params.actions; } /* * 初始化設定mutations物件 * 該物件主要處理同步事件 */ if (params.hasOwnProperty("mutations")) { self.mutations = params.mutations; } // 外掛 if (params.hasOwnProperty("plugins")) { self.plugins = params.plugins; } /* * 代理監聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設定state物件並賦值 state[key] = value; // 更改狀態 self.status = "resting"; return true; }, }); } dispatch = (actionKey, payload) => { const self = this; // 校驗是否存在函數 if (typeof self.actions[actionKey] !== "function") { console.warn(`Action ${actionKey} dose not exist`); return false; } // 變更狀態 self.status = "action"; // 執行對應函數,並傳入commit self.actions[actionKey]({ commit: self.commit }, payload); return true; } commit = (mutationKey, payload) => { const self = this; // 校驗是否存在函數 if (typeof self.mutations[mutationKey] !== "function") { console.warn(`Mutation ${mutationKey} dose not exist`); return false; } // 變更狀態 self.status = "mutation"; // 執行對應函數 self.mutations[mutationKey](self.state, payload); return true; } }複製程式碼
const SubPub = require("../lib/pubsub"); // 在state的代理中監測到資料改變,釋出相對應事件 class Store { constructor(params) { // 範例化釋出訂閱 self.events = new SubPub() ... /* * 代理監聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設定state物件並賦值 state[key] = value; // 新增釋出事件 self.events.publish("stateChange", self.state); // 更改狀態 self.status = "resting"; return true; }, }); ... } }複製程式碼
const Store = new Store({ state: { text: '' }, mutations: { init: (state, payload) => { state.text = payload }, }, actions: { init: ({commit},payload) => { setTimeout(() => { commit('init', payload) },200) } }, plugins: [ function() { console.log('plugins') } ] })// 執行同步事件Store.commit('init', 'hello init')// 執行非同步事件Store.dispatch('init', 'hello async init')複製程式碼
以上就是基礎版的全域性狀態管理器,包含基本的同步和非同步處理,外掛,釋出訂閱功能,當然還有些細節需要完善。有問題歡迎在評論中指出,謝謝。
相關免費學習推薦:(視訊)
以上就是你必須要掌握的前端狀態管理器的詳細內容,更多請關注TW511.COM其它相關文章!