Redux

单项数据类框架始祖Flux

Flux的目的是用来替代Backbone.js、Ember.js等MVC框架。

MVC框架将应用分为三个部分:
Model(模型) 负责管理数据,大部分业务逻辑放在Model中;
View(视图) 负责渲染用户界面,避免在View中涉及业务逻辑;
Controller(控制器) 负责接受用户的输入,根据用户的输入调用对应的Model部分的逻辑,把产生的数据交给View部分,让View渲染出必要的输出;
MVC框架的缺点
MVC框架提出的数据流很理想,但是在实际框架视线中,总是允许View和Model直接通信,从而出现以下情况。

MVC框架的缺点

在MVC框架中,系统能提供什么的服务,通过Controller 暴漏函数来实现。每增加一个功能,Controller就要增加一个函数。

Flux包含四个部分:
Dispatcher 处理动作分发,维持Store之间的依赖关系;
Store 负责存储数据和处理数据逻辑;
Action 驱动 Dispatcher 的 JavaScript 对象;
View 视图部分,负责显示用户界面;
在Flux中 Dispatcher 始终只需要暴漏一个函数Dispatch,当需要增加新的功能时,只用增加一种新的Action类型,Dispatcher 对外接口不改变。

Redux的基本原则

Flux的基本原则是“单向数据流”,Redux在此强调三个基本原则
1.唯一数据源
应用的状态应该只存储在唯一一个Store上,这个唯一Store上的状态,是一个树形的对象,每个组件往往只是树形象上的一部分数据,如何设计Store上状态的结构,就死Redux应用的核心问题。
2.保持状态只读
不能直接修改状态,要修改Store的状态,必须通过派发 action 对象完成。
3.数据改变只能通过纯函数完成
纯函数就是Reducer,reducer接受两个参数,第一个参数state是当前的状态,第二个参数action是接受到的action对象。

Action 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说会通过store.dispatch() 将 action 传到 store。
约定:action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。除了 type 字段外,action 对象的结构完全由你自己决定。
Action 创建函数
Action 创建函数 就是生成 action 的方法。“action” 和 “action 创建函数” 这两个概念很容易混在一起,使用时最好注意区分。在 Redux 中的 action 创建函数只是简单的返回一个 action:

function add(text) {
  return {
    type: TYPE_NAME,
    text
  }
}

Redux 中只需把 action 创建函数的结果传给 dispatch() 方法即可发起一次 dispatch 过程

dispatch(addTodo(text))

Reducers 指定了应用状态的变化如何响应actions并发送到 store 的,actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。

(previousState, action) => newState

reducer规范:(不能做)
修改传入参数;
执行有副作用的操作,如 API 请求和路由跳转;
调用非纯函数,如 Date.now() 或 Math.random()。

Store 就是把action、reducer联系到一起的对象。Store 有以下职责:

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;
  • 提供 dispatch(action) 方法更新 state;
  • 通过 subscribe(listener) 注册监听器;
  • 通过 subscribe(listener) 返回的函数注销监听器。

注意 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合而不是创建多个 store。
详细使用方法请看Redux中文文档

容器组件和展示组件

承担第一个任务的组件,也就是负责和 Redux Store 打交道的组件,处于外层,被称为容器组件;对于承担第二个任务的组件,也就是专心负责渲染界面的组件,处于内层,叫做展示组件

组件分工

展示组件是一个纯函数,根据 props 产生结果。

组件Context

在一个应用中,不同组件都会调用全局的Store,在组件中直接导入Store不利于组件复用,应该只在最顶层调用一次Store,将Store从上层组件传递给子组件,如果用props传递,所有的组件props都要增加对这个支持,很麻烦。React提供了一个Content的功能,能解决这个问题。
Context(上下文环境),让一个树状组件上所有组件都能访问一个共同的对象,需要上级组件和下级组件配合。

//定义在src文件夹下,是一个通用的 context 提供者
import React, {Component} from 'react'
import PropTypes from 'prop-types'

class Provider extends Component {
  getChildContext() {
    //返回的代表Context的对象
    return {
      store: this.props.store
    };
  }

  render() {
    //简单的把子组件渲染出来代表Provider标签之间的组件
    return this.props.children;
  }
}
//为了Provide比较通用,所以store从外部传递进来
//为了让Provider能够被React认可为一个Context提供者,需要指定Provider的childContextTypes
Provider.childContextTypes = {
  store: PropTypes.object
};


export default Provider;

每个React组件都有一个特殊属性 children,代表的是子组件。

子组件中对context的使用

className.contextTypes = {
  store: PropTypes.object
}

在子组件中对store的访问通过 this.context.store 完成。由于自定义了构造函数,所以构造函数要添加 context 参数

 constructor(props, context) {
   super(props, context);
   //es6 super(...arguments) 
}

context的使用:必须谨慎使用,只有对那些每个组件都可能使用,但是中间组件又不可能使用的对象才必须使用Context。

具体使用方法请参考聊一聊我对 React Context 的理解以及应用-张国钰

后记 将组件拆分为容器组件和展示组件,以及利用 React 的 Context 提供一个所有组件都可以直接访问的 Context,这两种方法都有自己的套路来改进 React 应用,可以将这两种方法的套路部分提取出来,已经有一个库实现,就是 react-redux

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容