实现一个简单的redux

616 阅读2分钟

1.状态管理

设计一个数据的时候,需要考虑什么问题

  1. 生命周期
  • DB 随着用户的登录,就存在,而且可以持久化
  • localStorage:跟随浏览器
  • sessionStorage:跟随窗口期
  • project runtime: 项目生命周期(redux),直到页面刷新或者关闭
  • page
  • component

2.redux包含的东西

createStore

  • createStore:这个API 最终返回一个Store对象,所有功能都在这个对象上

  • store.subscribe: 订阅state的变化,当state变化的是时候会执行回调,可以多个subscribe,里面的回调函数依次执行

  • store.dispatch :发出action方法,每次dispatch一个action都会执行,都会reducer函数,生成新的state,然后执行subscribe注册的回调。

  • store.getState:返回当前的State

     // 实现一个简单的发布订阅
       function createStore(initState) {
        let state = initState;
        let listeners = [];
    
        // 订阅的实现
        function subscribe(listener) {
          listeners.push(listener)
        }
    
        // 发布通知
        function dispatch(newState) {
          state = newState;
          // 发布
          for(let i =0 ;i< listeners.length ;i++) {
            listeners[i]();
          }
        }
    
        function getState() {
          return state;
        }
    
        return {
          getState,
          subscribe,
          dispatch
        }
      }
    
      const store = createStore();
    
      store.subscribe(() => {
        console.log('我是订阅1',store.getState())
      });
    
      store.subscribe(() => {
        console.log('我是订阅2',store.getState())
      });
    
      store.dispatch(10)
    

    以上存在的问题:

  • 多人开发中,不小心就会把数据清空,副作用太大。因此需要一个state的修改规则,告诉Store,要修改什么

  • reducer 就是告诉store,按照规范修改

      // 修改代码如下
      function createStore(reducer,initState) {
       let state = initState;
       let listeners = [];
    
       // 订阅的实现
       function subscribe(listener) {
         listeners.push(listener)
       }
    
       // 发布通知
       function dispatch(action) { // dispatch 的时候,如如何修改数据,而不是直接修改数据
         state = reducer(state, action); // 按照规则修改数据
         // 发布
         for(let i =0 ;i< listeners.length ;i++) {
           listeners[i]();
         }
       }
    
       function getState() {
         return state;
       }
    
       return {
         getState,
         subscribe,
         dispatch
       }
     }
    
     let initState = {
       count:0,
       age:18,
     };
    
     function reducer(state,action) {
       switch(action.type) {
         case "ADD_COUNT" : 
         return {...state,count:state.count + 1}
    
         case "MINUS" : 
         return {...state,count: state.count - 1}
       }
     }
    
     const store = createStore(reducer,initState);
    
     store.subscribe(() => {
       console.log('我是订阅1',store.getState())
     });
    
     store.subscribe(() => {
       console.log('我是订阅2',store.getState())
     });
    
     store.dispatch({type:"ADD_COUNT"})
    
     store.dispatch({type:"ADD_COUNT"})
    

多个reducer 如何解决

   function createStore(reducer,initState) {
      let state = initState;
      let listeners = [];

      // 订阅的实现
      function subscribe(listener) {
        listeners.push(listener)
      }

      // 发布通知
      function dispatch(action) { // dispatch 的时候,如如何修改数据,而不是直接修改数据
        state = reducer(state, action); // 按照规则修改数据
        // 发布
        for(let i =0 ;i< listeners.length ;i++) {
          listeners[i]();
        }
      }

      function getState() {
        return state;
      }

      return {
        getState,
        subscribe,
        dispatch
      }
    }

    let initState = {
      counter:{  count:0} ,
      info: {age:18},
    };

    function reducer(state,action) {
      switch(action.type) {
        case "ADD_COUNT" : 
        return {...state,count:state.count + 1}

        case "MINUS" : 
        return {...state,count: state.count - 1}

        default: 
        return state
      }
    }

    function reducer2(state,action) {
      switch(action.type) {
        case "ADD_INFO" : 
        return {...state,age:state.age + 1}
        case "MINUS_INFO" : 
        return {...state,age: state.age - 1}

        default:
          return state;
      }
    }

    function cobineReducers(reducers) {
      const keys = Object.keys(reducers);
      return function (state={},action) {
        const nextState = {}
        // 拿到所有的reducers,整合一个新的state
        for(let i=0;i<keys.length;i++) {
          const key = keys[i]; // 拿出一个reducer的key
          const reducer = reducers[key]; // 获取一个reducer

          const prev = state[key]; // 取当前执行reducer的state
          const next = reducer(prev,action); // 执行某个reducer获取最新的state
          nextState[key] = next;
        }
        return nextState;

      }
    }

    const reducers  = cobineReducers({
      counter:reducer,
      info:reducer2
    });

    const store = createStore(reducers,initState);

    store.subscribe(() => {
      console.log('我是订阅1',store.getState())
    });

    store.subscribe(() => {
      console.log('我是订阅2',store.getState())
    });

    store.dispatch({type:"ADD_COUNT"})
    setTimeout(() => {
      store.dispatch({type:"MINUS_INFO"})
    },1000)

redux-compose 如何处理副作用

  compose(...funcs) {
   return funcs.reduce((a,b) =>(...args) a(b(args)))
  }

3.react-redux

react-redux的核心

  • redux 是全局数据
  • redux 不会触发界面更新,react-redux用Context中 Provider 和consumer 将redux的store联系起来

4.react-redux 的实现

待补充