前言
一直想读一下redux的源码,这次终于安静下来好好读一下了。直接实现了一个自定义的createStore,感觉还不错,直接上代码。
结构
- currentState 缓存当前的state
- currentReducer 缓存当前的reducer
- currentListeners 注册监听的函数集合
let currentState = preloadState;
let currentReducer = reducer;
const currentListeners = [];
- dispatch 更改全局的state并触发监听的函数
function dispatch(action) {
currentState = currentReducer(currentState, action);
for (let listen of currentListeners) {
listen();
}
}
- subscribe 注册监听的函数
- unSubscribe 卸载当前注册的监听函数
function subscribe(listen) {
currentListeners.push(listen);
return function unSubscribe() {
const index = currentListeners.indexOf(listen);
currentListeners.splice(index, 1);
};
}
- replaceReducer 替换掉当前的reducer
function replaceReducer(nextReducer) {
currentReducer = nextReducer;
dispatch({ type: 'replaceReducer' });
}
createStore实现
export function crateStore(reducer, preloadState) {
let currentState = preloadState;
let currentReducer = reducer;
const currentListeners = [];
function getState() {
return currentState;
}
function dispatch(action) {
currentState = currentReducer(currentState, action);
for (let listen of currentListeners) {
listen();
}
}
function subscribe(listen) {
currentListeners.push(listen);
return function unSubscribe() {
const index = currentListeners.indexOf(listen);
currentListeners.splice(index, 1);
};
}
function replaceReducer(nextReducer) {
currentReducer = nextReducer;
dispatch({ type: 'replaceReducer' });
}
return { getState, subscribe, dispatch, replaceReducer };
}
使用
import { crateStore } from './custom/crateStore';
const reducer = (state, action) => {
switch (action.type) {
case 'add':
return { ...state, count: ++state.count };
case 'sub':
return { ...state, count: --state.count };
default:
return state;
}
};
const doubleCountReducer = (state, action) => {
switch (action.type) {
case 'add':
return { ...state, count: state.count * 2 };
case 'sub':
return { ...state, count: state.count * 2 };
default:
return state;
}
};
const store = crateStore(reducer, { count: 0 });
const unCountSubscript = store.subscribe(() => {
const count = store.getState().count;
console.log(count, '监听哈哈count');
});
function App() {
return (
<div className="App">
<button
onClick={() => {
unCountSubscript();
}}
>
停止监听
</button>
<button
onClick={() => {
store.replaceReducer(doubleCountReducer);
}}
>
注册双倍reducer
</button>
<button
onClick={() => {
store.dispatch({ type: 'add' });
const count = store.getState().count;
console.log(count, 'click');
}}
>
加数
</button>
</div>
);
}
export default App;