React:组件间数据流动(下)

        上篇文章中,讲述了 React 数据流方案中风格相对“朴素”的 Props 单向数据流方案,以及通用性较强的“发布-订阅”模式。本篇文章中将认识 React 天然具备的全局通信方式“Context API”,并对 Redux 的设计思想和编码形态进行初步的探索。

使用 Context API 维护全局状态
  Context API 是 React 官方提供的一种组件树全局通信的方式。在 React 16.3 之前,Context API 由于存在种种局限性,并不被 React 官方提倡使用,开发者更多的是把它作为一个概念来探讨。而从 v16.3.0 开始,React 对 Context API 进行了改进,新的 Context API 具备更强的可用性。首先针对 React 16 下 Context API 的形态进行介绍。

图解 Context API 工作流
  Context API 有 3 个关键的要素:React.createContext、Provider、Consumer。

  通过调用 React.createContext,可以创建出一组 Provider。Provider作为数据的提供方,可以将数据下发给自身组件树中任意层级的 Consumer,这三者之间的关系用一张图来表示:

 

注意:Cosumer 不仅能够读取到 Provider 下发的数据,还能读取到这些数据后续的更新。这意味着数据在生产者和消费者之间能够及时同步,这对 Context 这种模式来说至关重要。

从编码的角度认识“三要素”

  • React.createContext,作用是创建一个 context对象。下面是一个简单的用法示范:

注意,在创建的过程中,我们可以选择性地传入一个 defaultValue

const AppContext = React.createContext(defaultValue)

从创建出的 context对象中,我们可以读取到 Provider和 Consumer

  • Provider,可以理解为数据的 Provider(提供者)

 我们使用 Provider对组件树中的根组件进行包裹,然后传入名为“value”的属性,这个 value就是后续在组件树中流动的“数据”,它可以被 Consumer消费。使用示例如下:

<Provider value={title: this.state.title, content: this.state.content}>
      <Title />
      <Content />
</Provider>
  • Consumer,顾名思义就是“数据的消费者”,它可以读取 Provider下发下来的数据

其特点是需要接收一个函数作为子元素,这个函数需要返回一个组件。像这样:

<Consumer>
 	 {value => <div>{value.title}</div>}
</Consumer>

注意,当 Consumer没有对应的 Provider 时,value参数会直接取创建 context时传递给 createContext 的 defaultValue

第三方数据流框架“课代表”:初探 Redux
  对于简单的跨层级组件通信,我们可以使用发布-订阅模式或者 Context API 来搞定。但是随着应用的复杂度不断提升,需要维护的状态越来越多,组件间的关系也越来越难以处理的时候,我们就需要请出 Redux 来帮忙了。

什么是 Redux?

Redux 是 JavaScript 状态容器,它提供可预测的状态管理。

这句话背后的深意:

  • Redux 是为JavaScript应用而生的,也就是说它不是 React 的专利,React 可以用,Vue 可以用,原生 JavaScript 也可以用;
  • Redux 是一个状态容器,什么是状态容器?这里举个例子。

  假如把一个 React 项目里面的所有组件拉进一个群,那么 Redux 就充当了这个群里的“群文件”角色,所有的组件都可以把需要在组件树里流动的数据存储在群文件里。当某个数据改变的时候,其他组件都能够通过下载最新的群文件来获取到数据的最新值。这就是“状态容器”的含义——存放公共数据的仓库。

 

Redux 是如何帮助 React 管理数据的,Redux 主要由三部分组成:store、reducer 和 action。

  • store就好比组件群里的“群文件”,它是一个单一的数据源,而且是只读的;
  • action 人如其名,是“动作”的意思,它是对变化的描述。

下面这个对象就是一个 action

const action = {
  type: "ADD_ITEM",
  payload: '<li>text</li>'
}
  • reducer是一个函数,它负责对变化进行分发和处理, 最终将新的数据返回给 store

  storeaction 和 reducer三者紧密配合,便形成了 Redux独树一帜的工作流:

 

在 Redux 的整个工作过程中,数据流是严格单向的。

  对于一个 React 应用来说,视图(View)层面的所有数据(state)都来自 store(再一次诠释了单一数据源的原则)。

  如果你想对数据进行修改,只有一种途径:派发 action。action会被 reducer读取,进而根据 action内容的不同对数据进行修改、生成新的 state(状态),这个新的 state会更新到 store对象里,进而驱动视图层面做出对应的改变。

  对于组件来说,任何组件都可以通过约定的方式从 store 读取到全局的状态,任何组件也都可以通过合理地派发 action 来修改全局的状态。Redux 通过提供一个统一的状态容器,使得数据能够自由而有序地在任意组件之间穿梭。

从编码的角度理解 Redux 工作流

  接下来将站在编码的角度,探讨 Redux 的工作流,将上文中所提及的各个要素和流程具象化。

使用 createStore 来完成 store 对象的创建

// 引入 redux
import { createStore } from 'redux'
// 创建 store
const store = createStore(
    reducer,
    initial_state,
    applyMiddleware(middleware1, middleware2, ...)
);

createStore 方法是一切的开始,它接收三个入参:

  1. reducer;
  2. 初始状态内容;
  3. 指定中间件.

只有 reducer是必须要传的

reducer 的作用是将新的 state 返回给 store,一个 reducer一定是一个纯函数,它可以有各种各样的内在逻辑,但它最终一定要返回一个 state:

const reducer = (state, action) => {
    // 此处是各种样的 state处理逻辑
    return new_state
}

当我们基于某个 reducer去创建 store的时候,其实就是给这个 store指定了一套更新规则:

// 更新规则全都写在 reducer 里 
const store = createStore(reducer)

action 的作用是通知 reducer “让改变发生”

  要想让 state 发生改变,就必须用正确的 action 来驱动这个改变

前面我们已经介绍过 action的形态,这里再提点一下。首先,action是一个大致长这样的对象:

const action = {
  type: "ADD_ITEM",
  payload: '<li>text</li>'
}

action 对象中允许传入的属性有多个,但只有 type 是必传的。type是 action的唯一标识,reducer正是通过不同的 type来识别出需要更新的不同的 state,由此才能够实现精准的“定向更新”。

派发 action,靠的是 dispatch
  action 本身只是一个对象,要想让 reducer 感知到 action,还需要“派发 action”这个动作,这个动作是由 store.dispatch 完成的。

import { createStore } from 'redux'
// 创建 reducer
const reducer = (state, action) => {
    // 此处是各种样的 state处理逻辑
    return new_state
}
// 基于 reducer 创建 state
const store = createStore(reducer)
// 创建一个 action,这个 action 用 “ADD_ITEM” 来标识 
const action = {
  type: "ADD_ITEM",
  payload: '<li>text</li>'
}
// 使用 dispatch 派发 action,action 会进入到 reducer 里触发对应的更新
store.dispatch(action)

 从编码角度对 Redux 主要工作流的概括:

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值