自己簡寫一個redux(redux源碼簡寫)
- 2020 年 2 月 14 日
- 筆記
直接看程式碼
mydux.js文件 function createStore(reducer) { /** * 1.註冊用到的方法,並return出去提供使用 * 2.定義默認的狀態與事件池 * 3.默認先觸發一次dispatch給state賦予默認值 * 4.componentDidMount後會通過subscribe往狀態池中追加事件 * 5.在具體的事件處觸發dispatch,傳入具體的action,修改state的值,並且觸發事件池中的事件,從而更新組件 */ let state, listeners = []; function dispatch(action) { //傳入state和action,返回修改後最新的state狀態值 state = reducer(state, action); //通知事件事件池中的方法執行 for (let i = 0; i<listeners.length; i++){ let curFn = listeners[i]; if (typeof curFn === 'function') { curFn(); continue; } //不是函數的移除掉 listeners[i].splice(i, 1); i--; } } //組件通過getState獲取最新的狀態值(此處要深拷貝一下,避免組件直接通過對象引用修改狀態值,redux的源碼中貌似沒有深拷貝,存在一些缺陷) function getState() { return JSON.parse(JSON.stringify(state)); } function subscribe(fn) { //此處進行一個去重複,避免添加重複的事件(redux的源碼中貌似也沒有去重複,存在一些缺陷) for (let i = 0; i<listeners.length; i++){ if (listeners[i] === fn) { return; } } listeners.push(fn); //返回一個移除事件的函數,可以進行調用,從事件池中移除追加的事件 return function unsubscribe () { let index = listeners.indexOf(fn); if (index > -1) { // listeners.splice(index, 1); //這個地方不能用splice,可能會導致數組塌陷問題 listeners[index] = null; } }; } //創建的時候先調用一下,為了是當默認state沒值的時候,觸發reducer給初始化的state賦予一個默認值 dispatch({ type: `@@redux/INIT${Math.random()}` }); return { dispatch, getState, subscribe } } export { createStore }
App.js文件 import {createStore} from './redux/mydux.js' let store = createStore(reducer); window.store = store; function reducer(state = { n: 0, m: 0 }, action) { //reducer就是根據不同的行為標識來修改狀態資訊的 switch (action.type) { case 'support': state.n = state.n+1;break; case 'against': state.m = state.m+1;break; } return state; //return的是什麼,就會把store中的狀態改成什麼 }