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