简介
实现一个简单的Redux,以便更好地理解Redux
state
coust state = { count:1 } state.count = 2 console.log(state.count)//2
这样就可以直接改变state里面的值,但是改变state里面的值后没有人知道呀,所以引入发布订阅模式
subcribe
const listeners = [] function subscribe(listener){ listeners.push(listener) } subcribe(()=>{ state.count = count }) function setCount(count){ state.count = count listeners.forEach(item=>item()) } setCount(2)//2 setCount(3)//3
这样就知道改变数据了
代码封装
function createStore(initState) { let state = initState let listeners = [] //订阅 function subscribe(listener) { listeners.push(listener) } function changeState(newState) { listeners.forEach(item=>item()) state = newState } function getState() { return state } return { subscribe, changeState, getState } }
接下来创建一个store
let store = createStore(initState) store.subscribe(() => { let state = store.getState(); console.log(`${state.user.name}:${state.user.age}`); }); store.subscribe(() => { let state = store.getState(); console.log(state.counter.count); }); store.changeState({ ...store.getState(), user: { name: 'qweqweqwe', age: '1212' } }); store.changeState({ ...store.getState(), counter: { count: 12222 } });
reducer和action
改造如下
function createStore(initState, reducer) { let state = initState let listeners = [] //订阅 function subscribe(listener) { listeners.push(listener) } function dispatch(action) { listeners.forEach(item => item()) state = reducer(state, action) } function getState() { return state } return { subscribe, dispatch, getState } } let initState = { count: 0 } function reducer(state, action) { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 } break; case 'DECREMENT': return { ...state, count: state.count - 1 } break; default: break; } } let store = createStore(initState, reducer) store.dispatch({ type: 'INCREMENT' }) store.dispatch({ type: 'INCREMENT' }) store.dispatch({ type: 'DECREMENT' })
中间件
中间件是对dispatch的一个加强,下面是一个例子
记录日志中间件
//重写了dispatch方法,先用next缓存之前的dispatch方法 let store = createStore(initState, reducer) let next = store.dispatch store.dispatch = action => { console.log(`action:${action}`) console.log(`state:${store.getState()}`) next(action) console.log(`next state : ${store.getState()}`) }
记录异常
let store = createStore(initState, reducer) let next = store.dispatch store.dispatch = action => { try{ next(action) }catch(e){ throw new Error(e) } }
多中间件合作
function createStore(initState, reducer) { let state = initState let listeners = [] //订阅 function subscribe(listener) { listeners.push(listener) } function dispatch(action) { listeners.forEach(item => item()) state = reducer(state, action) } function getState() { return state } return { subscribe, dispatch, getState } } let initState = { count: 0 } function reducer(state, action) { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 } break; case 'DECREMENT': return { ...state, count: state.count - 1 } break; default: break; } } let store = createStore(initState, reducer) let next = store.dispatch const loggerMiddleware = function (next) { return function (action) { console.log('this state', store.getState()); console.log('action', action); next(action); console.log('next state', store.getState()); } } const exceptionMiddleware = function (next) { return function (action) { try { next(action); } catch (err) { console.error('错误报告: ', err) } } } store.dispatch = exceptionMiddleware(loggerMiddleware(next)) store.dispatch({ type: 'INCREMENT' }) console.log(store.getState())
不太理解的可以在浏览器debugger一遍,过程就很清晰了