Created
April 17, 2016 09:11
-
-
Save duncan60/12732ab7be704f5d7a231fc81c66248b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// createStore | |
const createStore = (reducer) => { | |
let state; | |
let listeners = []; | |
const getState = () => state; | |
const dispatch = (action) => { | |
state = reducer(state, action); | |
listeners.forEach(listener => listener()); | |
}; | |
const subscribe = (listener) => { | |
listeners.push(listener); | |
return () => { | |
listeners = listeners.filter(l => l !== listener); | |
}; | |
}; | |
dispatch({}); | |
return { getState, dispatch, subscribe }; | |
}; | |
//combinReducers | |
const combinReducers = (reducers) => { | |
return (state = {}, action) => { | |
return Object.keys(reducers).reduce( | |
(nextState, key) => { | |
nextState[key] = reducers[key](state[key], action); | |
return nextState; | |
}, | |
{} | |
); | |
} | |
} | |
// compose | |
const compose = (...funcs) => { | |
return (...args) => { | |
if (funcs.length === 0) { | |
return args[0]; | |
} | |
const last = funcs[funcs.length - 1]; | |
const rest = funcs.slice(0, -1); | |
return rest.reduceRight( | |
(composed, f) => { | |
return f(composed); | |
}, | |
last(...args) | |
); | |
}; | |
}; | |
// applyMiddleware | |
const applyMiddleWares = (...middlewares) => { | |
//將參數 middlewares 以陣列方式儲存 | |
return (next) => { | |
return (reducer, initialState) => { | |
let store = next(reducer, initialState), | |
// next 傳進原本的 createStore,在這邊create store | |
dispatch = store.dispatch, | |
//原本得store.dispatch指定給dispatch | |
chain = []; | |
var middlewareAPI = { | |
getState: store.getState, | |
dispatch: (action) => { | |
return dispatch(action); | |
} | |
}; | |
chain = middlewares.map((middleware) => { | |
return middleware(middlewareAPI); | |
}); | |
dispatch = compose(...chain)(store.dispatch); | |
/* | |
再度把dispatch改變, | |
store.dispatch 成為 chain 最後執行的動作, | |
所以middleWare 執行完後,最後曾執行到store.dispatch | |
*/ | |
return { | |
...store, | |
dispatch | |
}; | |
}; | |
}; | |
}; | |
//app | |
const appMiddlewareA = (middlewareAPI) => { | |
//初始 middleware 可以用 middlewareAPI 來初始化某些設定 | |
return (next) => { | |
return (action) => { | |
return next(action); | |
}; | |
}; | |
}; | |
const counter = (state = 0, action) => { | |
switch (action.type) { | |
case 'INCREMENT': | |
return state + 1; | |
case 'DECREMENT': | |
return state - 1; | |
default: | |
return state; | |
} | |
}; | |
const reducer = combinReducers({ | |
counter | |
}); | |
const newCreateStore = applyMiddleWares(appMiddlewareA)(createStore); | |
const store = newCreateStore(reducer, {}); | |
const render = () => { | |
document.body.innerText = store.getState().counter; | |
}; | |
store.subscribe(render); | |
render(); | |
document.addEventListener('click', () => { | |
store.dispatch({ type: 'INCREMENT' }); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo Link : https://jsbin.com/vobeja/edit?js,output