<!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>