创建插件
主要 API
- createStore
- getState
- dispatch
- subscribe
- combineReducers
- applyMiddleware // 新增
- logger // 新增
- crashReporter // 新增
Core
const combineReducers = (reducers) => {
return (state, action) => {
const combineState = {}
const keys = Object.keys(reducers)
for (let key of keys) {
const partial = reducers[key](state === undefined ? state : state[key], action)
combineState[key] = partial
}
return combineState
}
}
const applyMiddleware = (...middlewares) => {
return (store) => {
let dispatch = store.dispatch
middlewares.forEach(middleware => {
dispatch = middleware(store)(dispatch)
})
return {
...store,
dispatch
}
}
}
const createStore = (reducer, applyMiddleware) => {
let state = reducer(undefined, {})
const listener = []
const store = {
getState: () => {
return state
},
subscribe: (fn) => {
listener.push(fn)
},
dispatch: (action) => {
state = reducer(state, action)
for (let fn of listener) {
fn && fn()
}
}
}
return applyMiddleware(store)
}
增加日志功能
// 修改store,增加打印日志功能
const next = store.dispatch
store.dispatch = (action) => {
console.log('dispatching', action)
const result = next(action)
console.log('next state', store.getState())
return result
}
// 封装打印日志功能
const patchStoreToAddLogging = (store) => {
const next = store.dispatch
store.dispatch = (action) => {
console.log('dispatching', action)
const result = next(action)
console.log('next state', store.getState())
return result
}
}
// 使用打印功能
// patchStoreToAddLogging(store)
// 返回方法,防止直接修改dispatch,
const logger0 = (store) => {
const dispatch = store.dispatch
return (action) => {
console.log('dispatching', action)
const result = dispatch(action)
console.log('next state', store.getState())
return result
}
}
// 支持多个增强功能,不直接使用store上面的dispatch,使用传过来的,增强之后的dispatch
// 这就是完整版的插件
const logger1 = (store) => {
return (dispatch) => {
return (action) => {
console.log('dispatching', action)
const result = dispatch(action)
console.log('next state', store.getState())
return result
}
}
}
创建插件
打印日志插件
const logger = (store) => (dispatch) => (action) => {
console.log('dispatching', action)
const result = dispatch(action)
console.log('next state', store.getState())
return result
}
错误控制插件
const crashReporter = store => dispatch => action => {
try {
dispatch(action)
console.log('run in crash reporter')
} catch (error) {
console.log('handled error', error)
}
}
测试代码
const initCounterState = {
value: 0,
name: 'counter reducer'
}
const initTodoState = {
value: 0,
name: 'todo reducer'
}
const counterReducer = (state = initCounterState, action) => {
switch (action.type) {
case 'COUNTER/INCREMENT':
return {
...state,
value: state.value + (action.payload || 1)
}
case 'COUNTER/DECREMENT':
return {
...state,
value: state.value - (action.payload || 1)
}
default:
return {
...state
}
}
}
const todoReducer = (state = initTodoState, action) => {
switch (action.type) {
case 'TODO/INCREMENT':
return {
...state,
value: state.value + (action.payload || 1)
}
case 'TODO/DECREMENT':
return {
...state,
value: state.value - (action.payload || 1)
}
default:
return {
...state
}
}
}
const reducer = combineReducers({
counterReducer,
todoReducer,
})
const store = createStore(reducer, applyMiddleware(logger, crashReporter))
store.subscribe(() => {
const state = store.getState()
})
store.dispatch({
type: 'TODO/INCREMENT',
payload: 10
})
store.dispatch({
type: 'COUNTER/INCREMENT',
payload: 5
})
store.dispatch({
type: 'TODO/DECREMENT',
payload: 2
})