001 Redux 前世今生

11/1/2021 Redux

# Flux

Flux 本身既不是库,也不是框架,而是一种应用的架构思想,由 Facebook 团队提出,用来替代饱受诟病的MVC架构,是单向数据流的鼻祖、redux的前身。

# Flux 主要特点

  1. Store 包含状态和更改逻辑
  2. 有多个 Store
  3. 所有 Store 都互不影响且是平级的
  4. 有单一调度器
  5. React 组件订阅 store
  6. 状态是可变的

# Flux 主要有4部分组成

  1. Action

    顾名思义是一个动作指令, 如 {type: 'add'},通过该对象通知 Dispatcher 做出对应修改

    对于action对象的定义还有一套规范称为 FSA(Flux Standard Action)该规范定义了一个 Flux action 必须拥有一个 type 字段,可以拥有 errorpayloadmeta 字段。除此之外,不能有其他额外的字段。详见 https://github.com/acdlite/flux-standard-action

  2. Store

    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
    13
  3. Dispatcher (核心)

    Dispatcher 通过接收 Action 处理动作分发并维持store之间的依赖关系, 可以说 Dispatcheractionstore 连接到了一起, 不同的 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
    11
  4. View

    View 除了显示界面, 在修改界面时必须要发起一个action

  5. 上图 foo

简单案例-codesanbox (opens new window)

# Flux 的不足

  1. 代码冗余与store依赖

    Flux 的冗余代码太多。虽然 Flux 源码中几乎只有 dispatcher 的现实,但是在每个应用中都需要手动创建一个 dispatcher 的示例,且如果两个Store之间有逻辑依赖关系,还必须用上Dispatcher的waitFor函数。虽然Flux这个设计的确解决了Store之间的依赖关系,但是,这样明显的模块之间的依赖,看着还是让人感觉不大舒服,毕竟,最好的依赖管理是根本不让依赖产生。说到底,Flux 给开发者提供的还是它的思想。

  2. 难以进行服务器端渲染

    在Flux的体系中,有一个全局的Dispatcher,然后每一个Store都是一个全局唯一的对象,这对于浏览器端应用完全没有问题,但是如果放在服务器端,就会有大问题。

    和一个浏览器网页只服务于一个用户不同,在服务器端要同时接受很多用户的请求,如果每个Store都是全局唯一的对象,那不同请求的状态肯定就乱套了。

    并不是说Flux不能做服务器端渲染,只是说让Flux做服务器端渲染很困难,实际上,Facebook也说的很清楚,Flux不是设计用作服务器端渲染的,他们也从来没有尝试过把Flux应用于服务器端。

  3. Store混杂了逻辑和状态

    Store封装了数据和处理数据的逻辑,用面向对象的思维来看,这是一件好事,毕竟对象就是这样定义的。但是,当我们需要动态替换一个Store的逻辑时,只能把这个Store整体替换掉,那也就无法保持Store中存储的状态

# Redux

我们都知道 Flux 本身既不是库,也不是框架,而是一种应用的架构思想。而 Redux 呢,它的核心代码可以理解成一个库,但同时也强调与 Flux 类似的架构思想。从设计上看,Redux 参考了 Flux 的设计,但是对 Flux 许多冗余的部分(如 dispatcher)做了简化,但与Flux 最大的不同在于 不再像Flux以Dispatcher为中心

# Redux 的主要特点

  1. 唯一数据源

    带有分层 reducer 的单一 Store且 只有一个Store

  2. 状态是只读的

    这一点其实跟Flux的思想是一样的,只是在Flux案例中,我们可以直接修改状态,但在Redux中我们连store都没有,或者说不会想Flux 用代码去定义一个store

  3. 状态修改均由Reducer纯函数完成

# 工作原理

redux 规定只有一个store且数据均由reducer返回, 工作流程如图

foo

# 使用

  1. 定义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
  2. 创建 store 公共数据区域

    const store = createStore(reducer)
    export default store
    
    1
    2

    创建的store还包括4个方法

    1. getState() : 获取store中当前的状态
    2. dispatch(): 用于分发action
    3. subscribe(): 注册一个监听者,用于store变化时调用
    4. replaceReducer(): 更新当前store的reducer
  3. view

    // 获取数据
    console.log(store.getState());
    // 发送数据
    store.dispatch({type: 'XXXX', payload: {aaa: 'aaa'}})
    
    1
    2
    3
    4
Last Updated: 11/3/2021, 6:25:30 PM