从零到一搭建 react 项目系列之(七)

上一篇介绍了 react-router,今天介绍 redux。

什么是 Redux?

现如今,我们的项目都是由一个一个的模块组成的,组件化的思想更适合大且复杂的项目。

在此之前,React 并不适合写大型应用,因为它当时还没有很好地解决组件之间的通信问题。

为了解决这个问题,2014 年 Facebook 提出了 Flux 架构的概念,引发了很多的实现。2015 年,Redux 出现,将 Flux 与函数式编程结合在一起,很短时间内就成为了最热门的前端框架。

什么时候需要 Redux?

有人说过,挺有道理的哈。

如果你不知道是否需要 Redux,那就是不需要它。

在以下场景你可以考虑使用它:

  • 组件间需要共享状态
  • 状态需要在任何地方都能拿到
  • 一个组件需要改变另一个组件的状态
  • 一个组件需要改变全局状态

*以上内容引自阮一峰老师的博客,本教程是为了接入而接入,哈哈。

Redux 设计思想

  • Web 应用是一个状态机,View 与 State 是一一对应的。
  • 所有的状态,保存在一个对象里面。

基本概念和 API

先了解一下以下几个概念吧

  • Store:保存数据的容器。由 Redux 提供的 createStore 函数来生成唯一的 Store 对象。

  • StateStore 对象包含的数据。当前的状态,可通过 store.getState() 获取。Redux 规定一个 State 对应一个 View

  • ActionView 发出的动作(如用户点击鼠标等行为)通知 State 要发生改变。Action 是改变 State 的唯一办法。它是一个对象,其中 type 属性是必须的,表示 Action 的名称,其他属性可以自由设置,其社区有一个规范可以参考。如 const action = { type: 'SOMETHING_TODO', payload: 'SOME DATA' }

  • Action Creator:生成 Action 的函数。当有若干 Action 时,全部手写可能略显麻烦,可以定义一个函数来生成 Action,这种函数叫做 Action Creator

  • store.dispatch():是 View 发出 Action 的唯一方式。

  • Reducer:当 Store 收到 Action 之后,必须返回一个新的 State,这样 View 才会发生变化,这种 State的计算过程叫做 Reducer。它是一个纯函数。

  • Pure Function:即纯函数,同样的输入,必定得到同样的输出,且没有任何副作用

  • store.subscribe():监听 State 的变化,一旦 State 发生变化,就自动执行这个函数。它返回一个函数,执行该返回函数就解除监听。

实现最简单的 Store 案例

先安装 redux 依赖。

$ yarn add redux@4.0.4

src/js/store 目录下新建一个 index.js 文件。

// store/index.js
import { createStore } from 'redux'

// Reducer 处理函数
const reducer = (prevState, action) => {
  const { type, payload } = action
  switch (type) {
    case 'ADD':
      // 一定要不能修改 state,而是返回一个新的副本
      // 倘若 state 是引用数据类型,一定要借助 Object.assign、对象展开运算符(...)、其他库的拷贝方法或者自己实现深拷贝方法,返回一个新副本
      return prevState + payload
    case 'SUB':
      return prevState - payload
    default:
      // default 或者未知 action 时,返回旧的 state
      return prevState
  }
}

// 初始值
const initialState = 0

// 创建 Store(也可以不传入 initialState 参数,而将 reducer 中的 state 设置一个初始值)
const store = createStore(reducer, initialState)

// 监听 state 变化
// const unsubscribe = store.subscribe(() => {
//   console.log('监听 state 变化', store.getState())
// })

// 解除监听
// unsubscribe()

export default store

我们在 Home 组件引入 Store,并修改成:

// pages/home/index.js
import React, { Component } from 'react'
import store from '../../store'

class Home extends Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  // Action Creator 函数
  actionCreator(type, payload) {
    return { type, payload }
  }

  handle(type, val) {
    // 创建 Action
    const action = this.actionCreator(type, val)
    // 派发 Action
    store.dispatch(action)
    // 获取 State 快照
    console.log(`当前操作是 ${type},State 为:${store.getState()}`)
  }

  render() {
    return (
      <div>
        <h3>Home Component!</h3>
        <button onClick={this.handle.bind(this, 'ADD', 1)}>加一</button>
        <button onClick={this.handle.bind(this, 'SUB', 1)}>减一</button>
      </div>
    )
  }
}

export default Home

上面案例,我们做了一个很简单的加减操作。

通过 redux 提供的 createStore 函数创建了唯一的一个 store 对象,该函数接收三个参数 createStore(reducer, [preloadedState], enhancer) ,其中第一第二个分别是 reducer 函数和初始值,第三个一般是使用中间件时用到,我们后面会用到,这里暂不展开探讨。(点这里了解更多)

Reducer 函数接收两个参数 reducer(state, action),分别是 previousState(旧状态)Action。在首次执行 stateundefined,可以为它设置一个初始值,或者在 createStore 中传入。它有点类似 Array.prototype.reduce()

借助我们在 Home 组件下引入 store,并添加两个按钮,对 storestate 做加减操作。

🎉

至此

我们最简单 redux 案例实现了,但是这个距离我们想要的,还不够哦。

在此抛出几个问题:

  • 如何接入我们的 Component 了,当 state 发生变化时,使其自动更新 View?
  • 组件如何共享 Store?
  • 如何查看 State 的变化?

下文继续,未完待续…

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