美文网首页从零到一搭建 React 项目
从零到一搭建 react 项目系列之(七)

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

作者: 越前君 | 来源:发表于2020-08-27 18:31 被阅读0次

    上一篇介绍了 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 的变化?

    下文继续,未完待续…

    相关文章

      网友评论

        本文标题:从零到一搭建 react 项目系列之(七)

        本文链接:https://www.haomeiwen.com/subject/efchsktx.html