Skip to content

Instantly share code, notes, and snippets.

@duncan60
Created April 17, 2016 09:11
Show Gist options
  • Save duncan60/12732ab7be704f5d7a231fc81c66248b to your computer and use it in GitHub Desktop.
Save duncan60/12732ab7be704f5d7a231fc81c66248b to your computer and use it in GitHub Desktop.
// 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' });
});
@duncan60
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment