Redux源码
React更偏向于构建UI,虽然也能进行状态管理,但是面对大型复杂的项目,往往会面临跨组件通信,这时候就可以使用Redux。Redux是一种状态管理容器,他可以将组件用到的所有数据都保存在store中。
createStore
createStore(reducer, initialState, enhancer)用于创建一个store,第一个参数reducer用来修改store中的state,initialState为初始的state,enhancer是一个增强器,如果项目使用middleware的话,enhancer就是applyMiddleware的返回值,如果没有用middleware,则enhancer不传,
1 | export default function createStore(reducer, initialState, enhancer) { |
applyMiddleware
我们在上面说过了,applyMiddleware创建一个store的增强器,之所以增强,是因为dispatch被增强了,他是在原来的dispatch上附加了很多功能,具体是怎么实现的的,我们一起往下看
先给出中间件的写法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const middleware1 = middlewareAPI => next => action => {
console.log('m1 start')
const result = next(action)
console.log('m1 end')
return result
}
const middleware2 = middlewareAPI => next => action => {
console.log('m2 start')
const result = next(action)
console.log('m2 end')
return result
}
1 |
|
compose
compose方法最核心的就是使用Array.prototype.reduce,具体使用方法可以查看MDN,经过reduce之后得到的结果1
2
3
4
5
6
7
8
9
10
11
12
13
14
15export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
// compose(f, g, h) ====> (...args) => f(g(h(...args)))
// composeResult = compose(...chain) = (...args) => chain1(chain2(...args))
// dispatch = chain1(chain2(defaultDispatch))
新dispatch
我们用defaultDispatch表示最开始创建的dispatch(createStore中的dispatch),来看一下最后经过middleware包装过的dispatch长啥样1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46const chain1 = next => action => {
console.log('m1 start')
const result = next(action)
console.log('m1 end')
return result
}
const chain2 = next => action => {
console.log('m2 start')
const result = next(action)
console.log('m2 end')
return result
}
dispatch = chain1(chain2(defaultDispatch))
dispatch2 = action => {
console.log('m2 start')
const result = defaultDispatch(action)
console.log('m2 end')
return result
}
dispatch1 = action => {
console.log('m1 start')
const result = dispatch2(action)
console.log('m1 end')
return result
}
dispatch = action => {
console.log('m1 start')
// const result = dispatch2(action)
// ----------------------------------
console.log('m2 start')
const result = defaultDispatch(action)
console.log('m2 end')
// ----------------------------------
console.log('m1 end')
return result
}
这里也展示了middleware是洋葱模型,中间件的访问顺序是外 => 内 => 外,最内部其实是调用最原生的(createStore中定义的)dispatch,来调用reducer生成最新的state
另外可以看到middlewareAPI中的dispatch是1
2
3
4const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
而不是1
2
3
4const middlewareAPI = {
getState: store.getState,
dispatch: dispatch
}
是因为这里使用的是闭包,这样可以将经过中间件生成新的dispatch传给每一个中间件。