zoukankan      html  css  js  c++  java
  • Redux 源码自己写了一遍

    <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8">
            <title>Test</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
        </head>
        <body>
          <script type='text/javascript'>
            // var f = function( ...arg ){
            //     arg 是个数组
            //     ...arg 是传递进来的原封不动的值
            // }
    
            // const reducer = function(state, action){
            //   if(!state){
            //     state = initialState;
            //   }
            //   let nextState = _.deepClone(state);
    
            //   switch(action.type){
            //     case 'ADD_TODO':
            //       nextState.todos.push( action.payload );
            //       break;
            //     case 'INCREASE':
            //       nextState.counter = nextState.counter++;
            //       break;
            //     default:
            //       break;
            //   }
    
            //   return nextState;
            // }
    
    
            /*** compose ***/
            // compose(func3, func2, func1)(0);
            // 相当于写了 func3( func2( func1(0) ) )
            const compose = function( ...funcs ) {
              // 若没有传递参数, 则直接返还1个函数
              if ( funcs.length === 0 ) {
                return arg => arg;
              }
    
              // 若只有1个参数, 则直接返还这个函数
              if ( funcs.length === 1 ) {
                return funcs[0];
              }
    
              // 取出最后1个函数 当作 reduceRight的第2个参数
              const last = funcs[funcs.length - 1];
              // 取除了最后一个函数以外的函数数组
              const rest = funcs.slice(0, -1);
              // 所传递进来的参数 都当作 最后1个函数的参数
              return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
            }
    
            /*** combineReducers ***/
            const combineReducers = function(obj){
              return function(state, action){
                // nextState 为返回的新 state
                let nextState = {};
                for(var item in obj){
                  // obj[item] 为item 对应的reducer
                  /*
                    state[item] 的意思是 state 对应与 item 上的值,
                    比如 state 为 { counter: 0}, state[item]的值就为 0
                  */
                  nextState[item] = obj[item]( state[item], action );
                }
                return nextState;
              }
            }
    
            /*** bindActionCreators ***/
            const bindActionCreators = (obj, dispatch) => {
              let objNew = {};
              for(let i in obj){
                // item 为创建 action 的函数
                let item = obj[i];
                objNew[i] = (...args) => {
                  dispatch( item(...args) );
                }
              }
              return objNew;
            }
    
            /*** applyMiddleware ***/
            // 传入所有的中间件
            const applyMiddleware = (...middlewares) => {
              // 可以传入 createStore 作为参数
              return (createStore) => {
                // 这一步已经生成了 增强版本的 createStore
                return (reducer, initialState, enhancer) => {
                  
                  let store = createStore(reducer, initialState, enhancer);
    
                  // 这一步原来的写法是
                  // let chain = middlewares.map( middleware => middleware(store) );
                  // 源代码里是 从新创建了一个store
                  let storeNew = {
                    getState: store.getState,
                    dispatch: (action) => dispatch(action)
                  }
                  let chain = middlewares.map( middleware => middleware(storeNew) );
    
                  // 只有最后1个函数的传入了 store.dispatch 当作 dispatch,
                  // 其它函数都是最后1个函数的返回值当作 dispatch
                  const dispatch = compose(...chain)(store.dispatch);
    
                  /*
                    最早本来想下面那样写,
                    这个结果是所有中间件的 dispatch 都为 store.dispach
    
                    let chain = [...middlewares].map( (item) => {
                      return item(store)(store.dispatch);
                    } );
    
                    const dispatch = (action) => {
                      compose(...chain)(action);
                    };
                    
                    打印的结果为:
    
                    3 dispatch before
                    3 dispatch after
                    2 dispatch before
                    2 dispatch after
                    1 dispatch before
                    1 dispatch after
                    
                  */
    
                  return {
                    getState: store.getState,
                    subscribe: store.subscribe,
                    replaceReducer: store.replaceReducer,
                    dispatch: dispatch
                  }
                }
              }
            }
    
            /*** createStore ***/
            const createStore = function(reducer, initialState, enhancer){
              if( typeof enhancer === "function"){
                return enhancer(createStore)(reducer, initialState);
              }
    
              let state = initialState;
              // 操作的 listeners
              let listeners = [];
              let listenersCache = listeners;
    
              // 但凡 listeners 有变化, 比如push了 或者删除了, 都提前执行下 ensure
              const ensure = function(){
                // 若相等, 则拷贝一个新的 listeners
                if( listeners == listenersCache ){
                  listeners = listenersCache.slice();
                }
              }
    
              const getState = function(){
                return state;
              }
    
              const dispatch = function(action){
                state = reducer(state, action);
    
                // 为了让 ensure 执行成功
                listenersCache = listeners;
                let len = listenersCache.length;
                for(let i = 0; i < len; i++){
                  listenersCache[i]();
                }
    
                return action;
              }
    
              const subscribe = listener => {
                ensure();
                listeners.push(listener);
    
                return function(){
                  ensure();
                  listeners = listeners.filter(function(item, i){
                    return item != listener;
                  });
                }
    
              }
    
              dispatch({});
              return {
                dispatch: dispatch,
                getState: getState,
                subscribe: subscribe
              }
            }
    
            const initialState = {
              counter: 0,
              todos: []
            }
    
            const counterReducer = function(counter = 0, action){
              switch(action.type){
                case 'INCREASE':
                  console.log('Reducer increase');
                  return counter = counter + 1;
                default:
                  return counter;
              }
            }
    
            const todosReducer = function(todos = [], action){
              switch(action.type){
                case 'ADD_TODO':
                  return [...todos, action.payload];
                default:
                  return todos;
              }
            }
    
            const rootReducer = combineReducers({
              counter: counterReducer,
              todos: todosReducer
            });
    
            
            const actionAdd = (n) => {
              return {type: n}
            }
    
            const store = createStore(rootReducer, initialState);
    
            const actionCreate = bindActionCreators(
              {actionAdd: actionAdd},
              store.dispatch
            );
    
            store.subscribe(function(){
              console.log( store.getState() );
            });
    
            store.dispatch( actionAdd('INCREASE') );
            actionCreate.actionAdd('INCREASE');
            store.dispatch({type: 'ADD_TODO', payload: 'hello world'});
    
            console.log(' ---------- 分割线 ---------- ');
    
            // 中间件 1
            // 根据源代码 middlewareAPI 是一个新的对象, 类似 store
            // 只有store 里的dispatch 和 getState方法
            const middleware1 = ( middlewareAPI ) => {
              return (dispatch) => {
                return (action) => {
                  console.log( '1 dispatch before' );
    
                  // 这个 dispatch 其实是 middleware2 里的函数 (action) => {...}
                  let actionReturn = dispatch(action);
    
                  console.log( '1 dispatch after' );
                  return actionReturn;
                }
              }
            };
    
            const middleware2 = ( middlewareAPI ) => {
              return (dispatch) => {
                return (action) => {
                  console.log( '2 dispatch before' );
    
                  // 这个 dispatch 其实是 middleware3 里的函数 (action) => {...}
                  let actionReturn = dispatch(action);
    
                  console.log( '2 dispatch after' );
                  return actionReturn;
                }
              }
            };
    
            const middleware3 = ( middlewareAPI ) => {
              return (dispatch) => {
                return (action) => {
                  console.log( '3 dispatch before' );
    
                  // 这个 dispatch 才是 store.dispatch, 最终只有这里调用 reducer 更新
                  let actionReturn = dispatch(action);
    
                  console.log( '3 dispatch after' );
                  return actionReturn;
                }
              }
            };
    
            let enhancedCreateStore = applyMiddleware(middleware1, middleware2, middleware3)(createStore);
            let storeEnhance = enhancedCreateStore(rootReducer, initialState);
    
            /*
              最后的打印结果是:
    
              1 dispatch before
              2 dispatch before
              3 dispatch before
              Reducer increase
              3 dispatch after
              2 dispatch after
              1 dispatch after
            */
            storeEnhance.dispatch({type: 'INCREASE'});
    
          </script>
        </body>
    </html>
  • 相关阅读:
    position+left+bottom+top+right
    C++中的bool类型
    C++读取ini文件
    菜单中Clean和batch build的作用
    解决连接HIS连接不上数据库的问题
    编译错误ERROR C2027
    C++中枚举类型的作用
    用CTime类得到当前日期 时间
    C++中如何调用DLL文件
    #import "msado15.dll" no_namespace rename("EOF","adoEOF")
  • 原文地址:https://www.cnblogs.com/zhengming2016/p/6770486.html
Copyright © 2011-2022 走看看