隨著React和Vue等異步框架的廣泛運用,前端狀態(tài)管理器逐漸成為前端開發(fā)比不可少話題。形如React有倍受歡迎的Redux,再如Vue標配的狀態(tài)管理器Vuex,都是業(yè)內(nèi)相對成熟的狀態(tài)管理器,那么我們接下來就用原生javascript來實現(xiàn)一個狀態(tài)管理器。
主要包含兩個方面:第一是發(fā)布訂閱,第二是狀態(tài)管理。
發(fā)布訂閱PubSub創(chuàng)建類首先我們先創(chuàng)建一個PubSub類函數(shù):
class PubSub { constructor() { // 收集事件 this.events = {}; } }復(fù)制代碼實現(xiàn)Publish
接著我們來實現(xiàn)一個發(fā)布函數(shù):
class PubSub { ... // 發(fā)布 publish(event, data = {}) { const self = this; /* * 校驗是否存在事件 * 默認返回一個空數(shù)組 */ if (!self.events.hasOwnProperty(event)) { return []; } // 遍歷執(zhí)行事件隊列里的回調(diào)函數(shù) return self.events[event].map((callback) => callback(data)); } ... }復(fù)制代碼實現(xiàn)Subscribe
實現(xiàn)完發(fā)布函數(shù)publish,接著我們來實現(xiàn)訂閱函數(shù):
class PubSub { ... // 訂閱 subscribe(event, callback) { const self = this; /* * 校驗是否存在事件 * 默認給一個空數(shù)組 */ if (!self.events.hasOwnProperty(event)) { self.events[event] = []; } // 將事件推入回調(diào)隊列 return self.events[event].push(callback); } ... }復(fù)制代碼完整代碼
class PubSub { constructor() { // 收集事件 this.events = {}; } // 訂閱 subscribe(event, callback) { const self = this; /* * 校驗是否存在事件 * 默認給一個空數(shù)組 */ if (!self.events.hasOwnProperty(event)) { self.events[event] = []; } // 將事件推入回調(diào)隊列 return self.events[event].push(callback); } // 發(fā)布 publish(event, data = {}) { const self = this; /* * 校驗是否存在事件 * 默認返回一個空數(shù)組 */ if (!self.events.hasOwnProperty(event)) { return []; } // 遍歷執(zhí)行事件隊列里的回調(diào)函數(shù) return self.events[event].map((callback) => callback(data)); } }復(fù)制代碼狀態(tài)管理Store創(chuàng)建類
首先我們創(chuàng)建一個Store類函數(shù):
class Store { // 傳入params對象 constructor(params) { const self = this; self.actions = {}; // 異步任務(wù)對象 self.mutations = {}; // 同步任務(wù)對象 self.state = {}; // 全局狀態(tài)對象 self.plugins = []; // 插件 self.status = "resting"; // 初始狀態(tài) /* * 初始化設(shè)置actions對象 * 該對象主要處理異步事件 */ if (params.hasOwnProperty("actions")) { self.actions = params.actions; } /* * 初始化設(shè)置mutations對象 * 該對象主要處理同步事件 */ if (params.hasOwnProperty("mutations")) { self.mutations = params.mutations; } // 插件 if (params.hasOwnProperty("plugins")) { self.plugins = params.plugins; } /* * 代理監(jiān)聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設(shè)置state對象并賦值 state[key] = value; // 更改狀態(tài) self.status = "resting"; return true; }, }); } }復(fù)制代碼實現(xiàn)commit
接著我們來實現(xiàn)核心函數(shù)commit,該函數(shù)主要處理對象更改,調(diào)用mutations對象內(nèi)的函數(shù):
class Store { ... commit = (mutationKey, payload) => { const self = this; // 校驗是否存在函數(shù) if (typeof self.mutations[mutationKey] !== "function") { console.warn(`Mutation ${mutationKey} dose not exist`); return false; } // 變更狀態(tài) self.status = "mutation"; // 執(zhí)行對應(yīng)函數(shù) self.mutations[mutationKey](self.state, payload); return true; }; ... }復(fù)制代碼實現(xiàn)dispatch
實現(xiàn)完commit,我們再來實現(xiàn)dispatch,這個函數(shù)主要處理異步問題,傳入commit方法:
class Store { ... dispatch = (actionKey, payload) => { const self = this; // 校驗是否存在函數(shù) if (typeof self.actions[actionKey] !== "function") { console.warn(`Action ${actionKey} dose not exist`); return false; } // 變更狀態(tài) self.status = "action"; // 執(zhí)行對應(yīng)函數(shù),并傳入commit self.actions[actionKey]({ commit: self.commit }, payload); return true; }; ... }復(fù)制代碼完整代碼
class Store { // 傳入params對象 constructor(params) { const self = this; self.actions = {}; // 異步任務(wù)對象 self.mutations = {}; // 同步任務(wù)對象 self.state = {}; // 全局狀態(tài)對象 self.plugins = []; // 插件 self.status = "resting"; // 初始狀態(tài) /* * 初始化設(shè)置actions對象 * 該對象主要處理異步事件 */ if (params.hasOwnProperty("actions")) { self.actions = params.actions; } /* * 初始化設(shè)置mutations對象 * 該對象主要處理同步事件 */ if (params.hasOwnProperty("mutations")) { self.mutations = params.mutations; } // 插件 if (params.hasOwnProperty("plugins")) { self.plugins = params.plugins; } /* * 代理監(jiān)聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設(shè)置state對象并賦值 state[key] = value; // 更改狀態(tài) self.status = "resting"; return true; }, }); } dispatch = (actionKey, payload) => { const self = this; // 校驗是否存在函數(shù) if (typeof self.actions[actionKey] !== "function") { console.warn(`Action ${actionKey} dose not exist`); return false; } // 變更狀態(tài) self.status = "action"; // 執(zhí)行對應(yīng)函數(shù),并傳入commit self.actions[actionKey]({ commit: self.commit }, payload); return true; } commit = (mutationKey, payload) => { const self = this; // 校驗是否存在函數(shù) if (typeof self.mutations[mutationKey] !== "function") { console.warn(`Mutation ${mutationKey} dose not exist`); return false; } // 變更狀態(tài) self.status = "mutation"; // 執(zhí)行對應(yīng)函數(shù) self.mutations[mutationKey](self.state, payload); return true; } }復(fù)制代碼PubSub和Store結(jié)合引入PubSub庫
const SubPub = require("../lib/pubsub"); // 在state的代理中監(jiān)測到數(shù)據(jù)改變,發(fā)布相對應(yīng)事件 class Store { constructor(params) { // 實例化發(fā)布訂閱 self.events = new SubPub() ... /* * 代理監(jiān)聽state */ self.state = new Proxy(params.state || {}, { set(state, key, value) { // 代理設(shè)置state對象并賦值 state[key] = value; // 添加發(fā)布事件 self.events.publish("stateChange", self.state); // 更改狀態(tài) self.status = "resting"; return true; }, }); ... } }復(fù)制代碼實例場景
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') } ] })// 執(zhí)行同步事件Store.commit('init', 'hello init')// 執(zhí)行異步事件Store.dispatch('init', 'hello async init')復(fù)制代碼總結(jié)
當前標題:你必須要掌握的前端狀態(tài)管理器
文章起源:http://jinyejixie.com/article8/chship.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計公司、面包屑導(dǎo)航、定制網(wǎng)站、用戶體驗、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)