狀態管理器這麼火,讓咱們來作一個簡單的redux原理解析吧(vuex相似)

redux狀態管理器,實質上就是一個單例模式。咱們來實現一個簡單的redux模型,實現以前咱們要先熟悉它的用法。 redux

  • Redux是將整個應用狀態存儲到到一個地方,稱爲store裏面保存一棵狀態樹(state tree)
  • 組件能夠派發(dispatch)行爲(action)給store,而不是直接通知其它組件
  • 其它組件能夠經過訂閱store中的狀態(state)來刷新本身的視圖.

下面咱們按照這個思想來想一想怎麼作。 咱們來抽象一下,提取出最核心的思想,動用鬼斧神工畫個圖:數組

用文字來描述一下,一個惟一的倉庫裏,有一個私有屬性state,倉庫由門衛大哥進行管理,全部對state的操做都要通過門衛大哥,外面的人無權直接對state進行操做,若是有進行訂閱,則在狀態改變後收到狀態改變事件。好了,咱們按照這個思想來開始code吧函數

第一步:聲明一個對象

const state={
	a: 1
}

第二步:將對象包裹起來,使其不可隨意訪問

function createStore(){
	const state={
		a: 1
	}
}

第三步:暴露出一個方法,使外部能夠對狀態進行操做

function createStore() {
	 let state={
	    a:1
	  };
	function getState() {
		return state //此處直接將state返回,會使state引用地址暴露,從而被引用對象改變值
	}
	return {
		getState
	}
}
let store = createStore()  // 建立一個倉庫
let state = store.getState()  // 獲取狀態state
console.log(store.getState())  //  輸出{ a: 1 }
state.a = 2   //將state a的值設置爲2
console.log(state)  //  輸出爲{ a: 2 }
console.log(store.getState()) // 此時倉庫中state的值也改變了,輸出爲{ a: 2 }

因此咱們將第六行 return state 替換爲 return JSON.parse(JSON.stringify(state)) 能夠避免這個問題。優化

第四步:除了獲取狀態咱們還須要操做狀態,暴露第二個方法,dispatch,順便將state的初始化進行一下優化

'use strict'
function createStore() {
  let state;
 function getState() {
   return JSON.parse(JSON.stringify(state))
 }
 function dispatch(action) { // 分發
   state = reducer(state,action) // 接收當前 State 和Action做爲參數,返回一個新的 State
 }
 dispatch({ type: '@@INIT' }) // 在建立倉庫的時候,初始化state的值
 return {
   getState,
   dispatch
 }
}
let initState = {
  count: 0
}
//處理器,接收二個參數 ,接收老狀態和action,返回新狀態 
function reducer(state = initState, action) { // 若是state沒有值,默認值爲initState
   //判斷動做的類型
   switch (action.type) {
       case 'ADD_TODO': 
           return { ...state, count: action.number }; //...state解構state全部屬性,count: action.number覆蓋前面的值
       default:
           return state;
   }
}
let store = createStore()  // 建立一個倉庫
let state = store.getState()  // 獲取狀態state
let action = {
 type: 'ADD_TODO',
 number: 1
};
store.dispatch(action);  // 派發一個action,改變state的狀態
console.log(store.getState()) // 輸出{ count: 1 }

diapatch中執行咱們定義的reducer處理器函數,增刪改查。例子演示了先建立一個倉庫,在建立新倉庫的時候初始化了state。而後diapatch一個action:ADD_TODO,執行的處理是改變count的值,返回一個新的state對象,最後咱們能夠看到輸出,原來的state在初始化後變成{ count: 0 },又在ADD_TODO後變成了{ count: 1 }。spa

reducer函數是咱們在使用redux時須要本身定義的處理函數。code

至此,咱們已經實現了建立一個倉庫,而且能夠自定義一些處理函數對state進行操做。還缺了什麼呢?在實際項目中,狀態改變後咱們的大部分的組件須要當即獲得新的狀態,而後根據狀態改變做出不一樣的處理。也就是說組件對state進行一個監聽,一旦state發生改變,立馬通知到對應的組件。讓咱們來繼續實現吧。。。cdn

第五步:增長一個訂閱功能subscribe

function createStore() {
  let state;
  let listeners = [];
  
 function getState() {
   return JSON.parse(JSON.stringify(state))
 }
 
 function dispatch(action) { // 分發
   state = reducer(state,action); // 接收當前 State 和Action做爲參數,返回一個新的 State
   listeners.forEach(listener => listener()) // 一旦狀態改變,觸發全部的監聽函數,這裏須要優化,只有相關狀態改變才須要觸發
 }
 
 function subscribe(listener){ // 訂閱,若是需監聽狀態變化,將監聽函數傳過來
    listeners.push(listener); // 保存監聽函數到監聽數組
    return function () { // 返回取消訂閱的函數
      listeners = listeners.filter(item => item != listener); // 過濾監聽函數
    }
 }
 
 dispatch({ type: '@@INIT' }); // 在建立倉庫的時候,初始化state的值
 
 return {
   getState,
   dispatch,
   subscribe
 }
 
}

/*這裏是分割線,上面一部分是倉庫定義,下面部分是使用方法*/
let initState = {
  count: 0
}
//處理器,接收二個參數 ,接收老狀態和action,返回新狀態 
function reducer(state = initState, action) { // 若是state沒有值,默認值爲initState
   //判斷動做的類型
   switch (action.type) {
       case 'ADD_TODO': 
           return { ...state, count: action.number }; //...state解構state全部屬性,count: action.number覆蓋前面的值
       default:
           return state;
   }
}
let store = createStore()  // 建立一個倉庫

let action = { // 定義一個action
 type: 'ADD_TODO',
 number: 1
};

let unADD = store.subscribe(function(){ // 監聽狀態改變
  console.log('狀態改變了,如今的state爲:')  // 狀態改變了,如今的state爲:
  console.log(store.getState()) // { count: 1 }
})

store.dispatch(action);  // 派發一個action,改變state的狀態
複製代碼

鐺鐺鐺~,咱們的redux基本模型就作好了,有什麼不懂的能夠提問喲~對象

相關文章
相關標籤/搜索