plh97 / blog

✏️blog. writing in issues.
https://plhh.xyz/
82 stars 8 forks source link

[Redux] 简单实现 #164

Open plh97 opened 4 years ago

plh97 commented 4 years ago

视频解说: https://www.youtube.com/watch?v=QOUao86FPxg

实现步骤

  1. 发布订阅器实现 ✔️
  2. Reducer 实现 ✔️
  3. CombineReducer 实现 ✔️
  4. Middleware 实现 ✔️
  5. ApplyMiddleware 实现 [midd1, midd2] ✔️
  6. React-hooks + redux 实现 todo-list-filter UI MVC ✔️

代码

function CombineReducer(reducers) {
  return function combine(state, action) {
    const newState = {};
    Object.keys(reducers).forEach((key) => {
      newState[key] = reducers[key](state[key], action);
    });
    return newState;
  };
}
const CreateStore = (combination, initState, rewriteCreateStore) => {
  if (typeof initState === 'function') {
    return initState(CreateStore)(combination);
  }
  if (rewriteCreateStore) {
    return rewriteCreateStore(CreateStore)(combination, initState);
  }
  let state = {};
  const listeners = [];
  function subscript(cb) {
    listeners.push(cb);
    return function unsubscript() {
      listeners.splice(listeners.indexOf(cb), 1);
    };
  }
  function getState() {
    return state;
  }
  function dispatch(action) {
    state = combination(state, action);
    listeners.forEach((cb) => {
      cb();
    });
  }
  dispatch({ type: Symbol(1) });
  return {
    subscript,
    getState,
    dispatch,
  };
};

function ApplyMiddleware(middlewares) {
  return function rewriteCreateStoreFunc(oldCreateStore) {
    return function newCreateStore(reducer, initState) {
      const store = oldCreateStore(reducer, initState);
      let { dispatch } = store;
      const chains = middlewares.map((middleware) => middleware({ getState: store.getState }));
      chains.reverse().forEach((chain) => {
        dispatch = chain(dispatch);
      });
      store.dispatch = dispatch;
      return store;
    };
  };
}

export {
  CombineReducer,
  CreateStore,
  ApplyMiddleware,
};

Reference

redux原理全解 | 前端面试与进阶指南