简介
Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。不与任意 UI 库绑定。
Redux Flow
流程图
Flow Gif
核心 API 探索
核心 API List
@redux/src/index.ts
export {
createStore, //创建根 Store;采用闭包创建了 dispatch 等函数操作闭包内的对象
combineReducers, // 关联多个 reducer 一般用于大型应用的分区逻辑
bindActionCreators,
applyMiddleware, // 中间件逻辑
compose, // 多个 fuc 串联执行的封装
__DO_NOT_USE__ActionTypes
}
Redux.createStore
作用:创建根 Store;采用闭包创建了 dispatch 等函数操作闭包内的对象
核心代码:
/**
* Creates a Redux store that holds the state tree.
* The only way to change the data in the store is to call `dispatch()` on it.
*
* There should only be a single store in your app. To specify how different
* parts of the state tree respond to actions, you may combine several reducers
* into a single reducer function by using `combineReducers`.
*
...
const store = {
dispatch: dispatch as Dispatch<A>,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
} as unknown as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
return store
应用程序理论上只会使用一次createStore,剩余的所有操作均是对 createStore 拿到的 root store 做操作。
Store.dispatch
作用: 唯一一种改变 store 的方式
核心代码:
function dispatch(action: A) {
if (isDispatching) { // 如果正在 dispatch 则中断逻辑
throw new Error('Reducers may not dispatch actions.')
}
try {
isDispatching = true
currentState = currentReducer(currentState, action)
// 调用 reducer 的方法根据 action 重新计算 state
} finally {
isDispatching = false
}
const listeners = (currentListeners = nextListeners) // 发送state更新的广播
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
Store.getState
作用:获取最新的 state 镜像
/**
* Reads the state tree managed by the store.
*
* @returns The current state tree of your application.
*/
function getState(): S {
if (isDispatching) {
throw new Error(
'You may not call store.getState() while the reducer is executing. ' +
'The reducer has already received the state as an argument. ' +
'Pass it down from the top reducer instead of reading it from the store.'
)
}
return currentState as S
}
Store.subscribe
作用: 注册 state 变更的监听。返回 unsubscribe 用于取消监听防止内存泄漏
function subscribe(listener: () => void) {
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if (!isSubscribed) {
return
}
if (isDispatching) {
throw new Error(
'You may not unsubscribe from a store listener while the reducer is executing. ' +
'See https://redux.js.org/api/store#subscribelistener for more details.'
)
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
Redux.applyMiddleware
作用:redux 中间件,用于在 dispatch 方法执行前后进行切面操作
注意:中间的 dispatch 是 store.dispatch 没有经过任何中间件加强。
核心代码: @redux/
const middlewareAPI: MiddlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 遍历中间件形成中间件链
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
@redux/src/compose.ts
接收一个 func 数组,从左到右连接。内部使用了 Array 的 reduce 方法进行收拢。
/**
* Composes single-argument functions from right to left. The rightmost
* function can take multiple arguments as it provides the signature for the
* resulting composite function.
*
* @param funcs The functions to compose.
* @returns A function obtained by composing the argument functions from right
* to left. For example, `compose(f, g, h)` is identical to doing
* `(...args) => f(g(h(...args)))`.
*/
function compose(...funcs: Function[]) {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce(
(a, b) =>
(...args: any) =>
a(b(...args))
)
}
启发
- 代码中涉及到代码组合时考虑使用 componse 将函数进行组合方便后续扩展
- TODO