你必須要掌握的前端狀態管理器

2020-10-28 18:01:09

欄目教大家掌握前端狀態管理器。

狀態管理器

隨著ReactVue等非同步框架的廣泛運用,前端狀態管理器逐漸成為前端開發比不可少話題。形如React有倍受歡迎的Redux,再如Vue標配的狀態管理器Vuex,都是業內相對成熟的狀態管理器,那麼我們接下來就用原生javascript來實現一個狀態管理器。

主要包含兩個方面:第一是釋出訂閱,第二是狀態管理

釋出訂閱PubSub

建立類

首先我們先建立一個PubSub類函數:

class PubSub {  constructor() {  	// 收集事件
    this.events = {};
  }
}複製程式碼

實現Publish

接著我們來實現一個釋出函數:

class PubSub {
  ...  // 釋出
  publish(event, data = {}) {    const self = this;	
    /*
     * 校驗是否存在事件
     * 預設返回一個空陣列
     */
    if (!self.events.hasOwnProperty(event)) {      return [];
    }	
    // 遍歷執行事件佇列裡的回撥函數
    return self.events[event].map((callback) => callback(data));
  }
  ...
}複製程式碼

實現Subscribe

實現完釋出函數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

建立類

首先我們建立一個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

接著我們來實現核心函數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;
    };
    ...
}複製程式碼

實現dispatch

實現完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;
   }
}複製程式碼

PubSub和Store結合

引入PubSub庫

	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其它相關文章!