redux 三重境 - 对 redux 最佳实践的思考和总结

5,597 阅读5分钟
原文链接: zhuanlan.zhihu.com
1. 本文写在去年8月,有着我对redux最佳实践的思考和总结。


王国维的《人间词话》的三重境

古今之成大事业、大学问者,必经过三种之境界。

  • “昨夜西风凋碧树,独上高楼,望尽天涯路”,此第一境也;
  • “衣带渐宽终不悔,为伊消得人憔悴”,此第二境也;
  • “众里寻他千百度,蓦然回首,那人却在灯火阑珊处。”,此第三境也。




大纲

  1. redux 基础知识和 react-redux
  2. redux 周边生态探索
    • 有哪些功能?(粗略介绍)
    • 有哪些很不错的第三方库?(详细介绍)
  3. 最佳实践介绍(dva)




一: redux 基础知识和 react-redux

  1. 三个基本原则
  2. 数据流
  3. 在 React 应用中使用 Redux(react-redux)

redux 三个基本原则

  1. 整个应用只有唯一一个 Store 实例
  2. State 只能通过触发 Action 来更改
  3. State 的更改 必须写成纯函数(Reducer),(oldState, action) => newState,也就是每次更改总是返回一个新的 State


redux 两个显著的特点

  1. 可预测性(Reducer 是纯函数)。
  2. 扩展性强(middleware)。


单向数据流


  1. Actions 是 store.dispatch(action),它是每次数据改变的源头。
  2. 如果有 middleware 将先进入 middleware
  3. Reducer 管理 state, 也就是 (oldState, action) => newState 的集合。
  4. 当 state 改变后, View Provide 就会更改视图



连接 React (react-redux)

  1. 使用 Provider 在根组件 注入 Store
  2. 容器组件使用 connect() 方法连接 Redux

1. 使用 Provider 在根组件 注入 Store



2. 容器组件使用 connect() 方法连接 Redux

那么我们如何获取容器组件的依赖呢?

容器组件及其子组件需要的两个能力:

  1. 读数据:获取 redux 的 state
  2. 改数据:向 redux dispatch actions

使用步骤1


  1. mapStateToProps:从 store 的 state 里把容器组件依赖的部分 state 取出来,成为组件的 props。
  2. mapDispatchToProps: 将特定的 dispatch 函数取出来变为 props 。

注: bindActionCreators 将 ActionCreator 和 store 的 dispatch 绑定到一起,返回一个特定的 dispatch 函数,组件调用即可触发 store.dispatch(action)

使用步骤2

在 render 等函数里面 取出相应 props,自己使用或者传给子组件




分离容器组件和展示组件

redux 的重要思想:分离容器组件和展示组件。


容器组件

在应用中,只有 最顶层组件是对 Redux 可知。

展示组件

应该是“笨拙”的,是通过父组件传递的 props 来获取数据和更改数据的 dispatch,它是感知不到 redux 存在的,具有很强的复用性。



如何分辨容器组件和展示组件的思考

1. 状态

  • 容器组件维护多个状态
  • 展示组件维护极少的状态(一般是 ui 状态)

2. ui

  • 容器组件无关 ui,几乎没有 css 样式、html 标签,通过组合展示组件来构造容器组件
  • 展示组件 ui 强相关,大量 css 和 html 标签

容器组件示例(ArticleBox 组件):



展示组件示例(Article 组件):



容器组件和展示组件对比


二: 探索阶段



  • 探索 redux 生态
    • 有哪些功能?(粗略介绍)
    • 有哪些很不错的第三方库?(详细介绍)
  • 最佳实践介绍(dva)

redux 生态

  • 连接到其他库
  • 开发(debug)工具
  • 各类实用工具
    • 简化 api
    • 计算、处理数据
    • 异步 action

连接到其他库

  • react-redux
  • react-router-redux
  • redux-immutablejs

实用工具

  • redux-thunk — 用最简单的方式书写异步 action creator
  • redux-actions — 在初始化 reducer 和 action 构造器时减少样板代码
  • Reselect Data => View store 的 select 方案,用于提取数据的筛选逻辑。
  • 等等

开发测试工具

devtool

redux-devtools — 一个使用时间旅行 UI 、热加载和 reducer 错误处理器的 action 日志工具



DevTools accepts monitor components(Custom Monitors)



Redux Logger

  • redux-logger — 记录所有 Redux action 和下一次 state 的日志


不错的第三方库




我这里就介绍一个第三方库

  • redux-action

简化 redux api

redux-actions — 在初始化 reducer 和 action 构造器时减少样板代码

createAction

下图这是 createAction 的效果 (我把我博客的 actions refactor 一下,上面是简化后。)



内部实现

原理就是高阶函数, createAction 返回一个函数,



三: 最佳实践

dva 介绍

google dva...第一个结果

dva 框架

实际上 dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装,没有引入任何新概念,全部代码不到 100 行。

由支付宝前端团队开发。

他们总结的 React + Redux 最佳实践


dva 的由来

dva 特点

api 风格方面非常像 vue,并且沿袭了 vue 的简单易上手、api 简洁的特点。

dva 使用


关于 dva 的思考

react redux

react redux 的思想从一开始就是 开放的,海纳百川,官方给出的最佳实践是 组合式 的,根据需求、喜好的不同,会有十几种最佳实践。。。。

  • 优点:社区异常活跃;扩展性强、非常灵活;中台组件库基于 React。
  • 缺点:学习成本高,新手上手慢;太灵活,周边生态百花齐放,如果没有一定的约束,非常不易于团队合作。

vue

去年开始 vue 以上手容易、api 简洁优雅出名,对于同类需求,官方给出的最佳实践几乎是唯一的。

  • 优点:学习成本低,易上手;最佳实践统一,利于团队合作;作者非常给力,在 vue2.0 里,发布了很多特别棒的新 feature(jsx,virtual dom,服务器流式渲染); weex 扩展了 vue 在移动端的能力。
  • 缺点:社区活跃低于 React;扩展性、灵活性差。

dva

dva 结合了 react 和 vue 两者的优点

  • 学习成本低,易上手
  • 最佳实践统一,利于团队合作
  • 社区异常活跃,扩展性强
  • 中台 dpl 基于 React

缺点:

  • 降低了 redux 的扩展性、灵活性

对 dva 的态度

  1. 学习借鉴
    • 学习思想,借鉴他们的最佳实践; 持续跟进
  2. 使用? or 自己造轮子?
    • 使用: 当其比较成熟时,对于复杂页面(尤其是单页应用)可以考虑使用。
    • or 自己造轮子: 借鉴学习其的特点和功能自己造轮子