一 Redux简介
Redux 是 JavaScript 状态容器,提供可预测化的状态管理
动机与目的
JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)。
state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等
管理不断变化的 state 非常困难。state 在什么时候,由于什么原因,如何变化已然不受控制。
一些库如 React 试图在视图层禁止异步和直接操作 DOM 来解决这个问题。
美中不足的是,React 依旧把处理 state 中数据的问题留给了你。Redux就是为了解决这个问题。
跟随 Flux、CQRS 和 Event Sourcing 的脚步,通过限制更新发生的时间和方式,
Redux 试图让 state 的变化变得可预测。这些限制条件反映在 Redux 的 三大原则中.
Redux三大原则:
(1)单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
(2)State 是只读的,惟一改变 state 的方法就是触发 action:action 是一个用于描述已发生事件的普通对象。视图和网络请求都不能直接修改 state,它们只能表达想要修改的意图。所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心 race condition 的出现。 Action 是普通对象,可以被日志打印,后期调试或测试时回放出来。
(3)使用纯函数reducers来执行修改:为了描述 action 如何改变 state tree ,需要编写 reducers,reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。刚开始可以只有一个 reducer,随着应用变大,可以拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,甚至编写可复用的 reducer 来处理一些通用任务,如分页器。
优势:
可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用)
简单清量(只有2kB)且没有任何依赖
由 Flux 演变而来,但受 Elm 的启发,避开了 Flux 的复杂性
做复杂应用和庞大系统时优秀的扩展能力。
可以用 action 追溯应用的每一次修改 (因此才有强大的开发工具。如录制用户会话并回放所有 action 来重现它)
单一的state tree:让同构应用开发变得非常容易。来自服务端的 state 可以在无需编写更多代码的情况下被序列化并注入到客户端中。调试也变得非常容易。
和Flux的比较
同:
和 Flux 一样,Redux 将模型的更新逻辑集中于一个特定的层(Flux 里的 store,Redux 里的 reducer)。
Flux 和 Redux 都不允许程序直接修改数据,而是用一个叫作 “action” 的普通对象来对更改进行描述。
异:
1.Redux 没有 Dispatcher ,且不支持多个 store。
相反,只有一个单一的 store 和一个根级的 reduce 函数(reducer)。
随着应用不断变大,应该把根级的 reducer 拆成多个小的 reducers,
分别独立地操作 state 树的不同部分,而不是添加新的 stores。
这就像一个 React 应用只有一个根级的组件,这个根组件又由很多小组件构成。
二 Redux安装
安装稳定版:
npm install –save redux
多数情况下,还需要使用React 绑定Redux的库和开发者工具
npm install –save react-redux
npm install –save-dev redux-devtools
三 Redux技术要点
应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。
惟一改变 state 的办法是触发 action,一个描述发生什么的对象。
为了描述 action 如何改变 state 树,你需要编写 reducers。
一个简单的例子:
import { createStore } from 'redux';
/**
* 这是一个 reducer,形式为 (state, action) => state 的纯函数。
* 描述 action 如何把 state 转变成下一个 state。
*
* state 的形式可以是基本类型、数组、对象等数据结构。惟一的要点是:
* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
*
* 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
*/