001 Redux 前世今生
# Flux
Flux 本身既不是库,也不是框架,而是一种应用的架构思想,由 Facebook 团队提出,用来替代饱受诟病的MVC架构,是单向数据流的鼻祖、redux的前身。
# Flux 主要特点
- Store 包含状态和更改逻辑
- 有多个 Store
- 所有 Store 都互不影响且是平级的
- 有单一调度器
- React 组件订阅 store
- 状态是可变的
# Flux 主要有4部分组成
Action
顾名思义是一个动作指令, 如 {type: 'add'},通过该对象通知
Dispatcher做出对应修改对于action对象的定义还有一套规范称为 FSA(Flux Standard Action)该规范定义了一个 Flux action 必须拥有一个
type字段,可以拥有error、payload或meta字段。除此之外,不能有其他额外的字段。详见 https://github.com/acdlite/flux-standard-actionStore
Flux 中的 Store 类似于 model,用来 存储数据 并定义 数据修改的逻辑
如:
const store = Object.assign(EventEmitter.prototype, { items: [], emitChange() { this.emit('change'); }, addChangeListener(callback) { this.on('change', callback); }, addItem(text) { this.items.push(text); }, });1
2
3
4
5
6
7
8
9
10
11
12
13Dispatcher (核心)
Dispatcher通过接收Action处理动作分发并维持store之间的依赖关系, 可以说Dispatcher将action及store连接到了一起, 不同的action通过swich调取不同的数据修改逻辑flux.register(function(action) { switch (action.type) { case 'add': const { text } = action.payload; store.addItem(text); break; default: break; } store.emitChange(); });1
2
3
4
5
6
7
8
9
10
11View
View除了显示界面, 在修改界面时必须要发起一个action上图

简单案例-codesanbox (opens new window)
# Flux 的不足
代码冗余与store依赖
Flux 的冗余代码太多。虽然 Flux 源码中几乎只有 dispatcher 的现实,但是在每个应用中都需要手动创建一个 dispatcher 的示例,且如果两个Store之间有逻辑依赖关系,还必须用上Dispatcher的waitFor函数。虽然Flux这个设计的确解决了Store之间的依赖关系,但是,这样明显的模块之间的依赖,看着还是让人感觉不大舒服,毕竟,最好的依赖管理是根本不让依赖产生。说到底,Flux 给开发者提供的还是它的思想。
难以进行服务器端渲染
在Flux的体系中,有一个全局的Dispatcher,然后每一个Store都是一个全局唯一的对象,这对于浏览器端应用完全没有问题,但是如果放在服务器端,就会有大问题。
和一个浏览器网页只服务于一个用户不同,在服务器端要同时接受很多用户的请求,如果每个Store都是全局唯一的对象,那不同请求的状态肯定就乱套了。
并不是说Flux不能做服务器端渲染,只是说让Flux做服务器端渲染很困难,实际上,Facebook也说的很清楚,Flux不是设计用作服务器端渲染的,他们也从来没有尝试过把Flux应用于服务器端。
Store混杂了逻辑和状态
Store封装了数据和处理数据的逻辑,用面向对象的思维来看,这是一件好事,毕竟对象就是这样定义的。但是,当我们需要动态替换一个Store的逻辑时,只能把这个Store整体替换掉,那也就无法保持Store中存储的状态
# Redux
我们都知道 Flux 本身既不是库,也不是框架,而是一种应用的架构思想。而 Redux 呢,它的核心代码可以理解成一个库,但同时也强调与 Flux 类似的架构思想。从设计上看,Redux 参考了 Flux 的设计,但是对 Flux 许多冗余的部分(如 dispatcher)做了简化,但与Flux 最大的不同在于 不再像Flux以Dispatcher为中心
# Redux 的主要特点
唯一数据源
带有分层 reducer 的单一 Store且 只有一个Store
状态是只读的
这一点其实跟Flux的思想是一样的,只是在Flux案例中,我们可以直接修改状态,但在Redux中我们连store都没有,或者说不会想Flux 用代码去定义一个store
状态修改均由Reducer纯函数完成
# 工作原理
redux 规定只有一个store且数据均由reducer返回, 工作流程如图
# 使用
定义reducer
// 设置默认值 const initialState = { counter: 0 } const reducer = (state = initialState, action) => { switch (action.type) { case 'XXXX': return {...state, ...action.payload} default: return state } }1
2
3
4
5
6
7
8
9
10
11
12创建 store 公共数据区域
const store = createStore(reducer) export default store1
2创建的store还包括4个方法
- getState() : 获取store中当前的状态
- dispatch(): 用于分发action
- subscribe(): 注册一个监听者,用于store变化时调用
- replaceReducer(): 更新当前store的reducer
view
// 获取数据 console.log(store.getState()); // 发送数据 store.dispatch({type: 'XXXX', payload: {aaa: 'aaa'}})1
2
3
4