You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importcomposefrom'./compose'/** * @param {...Function} * @returns {Function} */exportdefaultfunctionapplyMiddleware(...middlewares){returncreateStore=>(...args)=>{// 正常的进行初始化conststore=createStore(...args)letdispatch=()=>{thrownewError('Dispatching while constructing your middleware is not allowed. '+'Other middleware would not be applied to this dispatch.')}// 每个 middleware 需要传入的参数constmiddlewareAPI={getState: store.getState,dispatch: (...args)=>dispatch(...args)//这里 dispatch 是一个引用,后面修改了这里也会影响}// 传入的参数通过 ... 转换放入 middlewares 数组中,统一执行传入的函数constchain=middlewares.map(middleware=>middleware(middlewareAPI))// 返回按照传入参数顺序的调用函数,如果是多个,会返回一个嵌套的函数dispatch=compose(...chain)(store.dispatch)return{
...store,
dispatch
}}}
exportdefaultfunctioncompose(...funcs){if(funcs.length===0){// infer the argument type so it is usable in inference down the linereturn(arg)=>arg;}if(funcs.length===1){returnfuncs[0];}returnfuncs.reduce((a,b)=>(...args)=>a(b(...args)));}
目录
引子
之前看过一些对于 redux 源码的解读,现在想按照自己的想法写一写。
从 2018.04.18 Redux v4.0.0 之后就没有发过大的版本了,现在处于一个很稳定的阶段。
下面是查看代码所处分支、时间、commit 的信息:
基本概念
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。可以和很多框架配合使用。
Redux 三大原则:
state
被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个store
中。action
,action
是一个用于描述已发生事件的普通对象。reducer
。Action
描述有事情发生,它把数据从应用传到store
的有效载荷。它是store
数据的唯一来源。Action 创建函数
就是生成action
的方法。Reducers
指定了应用状态的变化如何响应action
并发送到store
。action
描述“发生了什么”,使用reducer
来根据action
更新state
,Store
就是把它们联系到一起的对象。详细介绍见官方文档。
下面结合官方文档中的例子去看源码。
主要实现
在文档
基础(Basic Tutorial)
一章中,先提供了一个纯 JavaScript 的例子,这里取其中一部分完整的逻辑如下。从例子里面可以发现,
action
和reducer
都是很常见的函数和对象,在 index.js 文件里面才出现了跟 redux 相关的调用,首先看下createStore(todoApp)
做了什么。API 文档中说是创建一个 Redux store 来以存放应用中所有的 state,有三个参数依次是:
在
createStore(todoApp)
中用到了第一个参数,传参也符合文档描述要求。看了源码后,发现除了文档说的作用,还有其它的作用。先列出
createStore
方法中主要组成其中
ActionTypes.INIT
并不是createStore
的内部变量,找到后是这样的:差不多齐了,可以发现在
createStore
执行后除了对外提供一些常见的接口,主要就执行了一次dispatch
, 触发了一次 state 初始化操作,那么接着就是看下dispatch
方法里面做了什么。除去检查和容错处理代码,主要的逻辑如下:处理的逻辑:
currentReducer
就是一开始传给createStore
的参数todoApp
,也就是reducers.js
文件里面导出的方法todoApp
,这时传入的ActionTypes.INIT
在程序中没有匹配,返回了默认的initialState
。初始化的过程就这样结束了。这个函数里面就是 redux 的主要实现逻辑,简单来说就是将我们自己编写的
action
和reducer
,通过dispatch
方法一一对应起来,每次想要改变state
,必须要通过dispatch
方法。例如index.js
文件里面后面执行的语句:addTodo
是 action 创建函数,返回的结果是{ type: 'ADD_TODO', 'Learn about redux' }
,通过dispatch
方法,将这个结果传递了reducers.js
里面的todoApp
方法接收,进行相应的处理后,返回了新的state
值{todos:[{text: 'Learn about redux', completed: false}]}
。更加详细的代码和注释见源文件 createStore.js。
其它 API 实现
下面针对其它 API 的实现介绍一下。
combineReducers
使用:combineReducers(reducers)
作用:是把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法。
参数:reducers 是一个对象,它的值(value)对应不同的 reducer 函数。
列出主要相关代码:
combineReducers 方法主要逻辑是:
applyMiddleware
使用:applyMiddleware(...middlewares)
作用:扩展 Redux 的一种方式,可以让包装 store 的 dispatch 方法来达到想要的目的,例如使用
redux-thunk
中间件来实现异步 action。返回值:是一个函数
首先来看下官网在
高级(Advanced Tutorial)
中讲解异步 Action(Async Actions)
使用的示例:上面有提到
createStore
方法的第二个参数是初始的 state,这里怎么传了一个函数?原因是在createStore
对参数做了下面的判断:这样就相当于是执行了
再来看
applyMiddleware
方法做了什么处理,下面是源码:以示例中
thunk
为例,看下最终的 dispatch 是什么样子。下面是redux-thunk
源码。按照上面的逻辑,将这个函数传入其中:
当示例中调用同步的 action 的时候
store.dispatch(selectSubreddit('reactjs'))
,实际上执行的是 redux 自己原本的 dispatch 方法。下面看下异步的 action 。异步的 action 返回的是一个函数,当
dispatch
时,就会执行这个函数,这个函数返回的是一个Promise
,里面有相关的请求处理,等结果返回后,还是调用redux
最基本的dispatch
方法触发 state 更新。compose
从右到左组合函数。下面是源码:
就像注释里面的举例,将
compose(f,g,h)(...args)
转换为f(g(h(...args)))
。思考
看完 Redux 的主要逻辑后,一开始觉得有点惊讶,它好的地方除了文档上的描述的优点,还有什么?后来想到里面强调的一个“纯函数”的概念,去了解后才感觉到其中妙的地方。
纯函数带来的好处:
再来看一下在学校里面函数的概念:
纯函数就是数学上的函数。这一点让我想到平时编程的时候,好像也写过类似
y=x+1
的程序,但 Redux 在实现的时候不仅运用这种思想,在整体使用方式上,个人觉得也是遵循了这种思想, Action、Reducer 分别相当于函数中的 x、y,Redux 相当于函数的对应关系。回想起之前工作中碰到使用 MVC 模式,其中掺杂了不同的相互调用,数据状态混乱,排查问题耗时麻烦。现在想想如果也采用这种函数的思想,也是可以在一定程度上,达到状态清晰的效果。还有就是对抽取公共方法的思考,为了兼容各种情况,对于相同的输入可能得到不同的结果,这种方式是否合理,使用纯函数的方式是否更好。
把简单的思想巧妙的运用和扩展,这是个人感觉 Redux 最妙的地方。
参考资料
🗑️
看了一个纪录片《地平线系列之:阻止男性自杀》,上映的时间是 2019.9,里面有些信息:
在中国这似乎是个很忌讳的问题。
The text was updated successfully, but these errors were encountered: