• 17【redux】


    17 【redux

    引言

    我们现在开始学习了 Redux ,在我们之前写的案例当中,我们对于状态的管理,都是通过 state 来实现的,比如,我们在给兄弟组件传递数据时,需要先将数据传递给父组件,再由父组件转发 给它的子组件。这个过程十分的复杂,后来我们又学习了消息的发布订阅,我们通过 pubsub 库,实现了消息的转发,直接将数据发布,由兄弟组件订阅,实现了兄弟组件间的数据传递。但是,随着我们的需求不断地提升,我们需要进行更加复杂的数据传递,更多层次的数据交换。因此我们为何不可以将所有的数据交给一个中转站,这个中转站独立于所有的组件之外,由这个中转站来进行数据的分发,这样不管哪个组件需要数据,我们都可以很轻易的给他派发。

    而有这么一个库就可以帮助我们来实现,那就是 Redux ,它可以帮助我们实现集中式状态管理

    1.简介

    Redux – 李立超 | lilichao.com

    李立超老师的解释

    A Predictable State Container for JS Apps是Redux官方对于Redux的描述,这句话可以这样翻译“一个专为JS应用设计的可预期的状态容器”,简单来说Redux是一个可预测的状态容器,什么玩意?这几个字单独拿出来都认识,连到一起后怎么就不像人话了?别急,我们一点一点看。

    1.1 状态(State)

    state直译过来就是状态,使用React这么久了,对于state我们已经是非常的熟悉了。state不过就是一个变量,一个用来记录(组件)状态的变量。组件可以根据不同的状态值切换为不同的显示,比如,用户登录和没登录看到页面应该是不同的,那么用户的登录与否就应该是一个状态。再比如,数据加载与否,显示的界面也应该不同,那么数据本身就是一个状态。换句话说,状态控制了页面的如何显示。

    但是需要注意的是,状态并不是React中或其他类似框架中独有的。所有的编程语言,都有状态,所有的编程语言都会根据不同的状态去执行不同的逻辑,这是一定的。所以状态是什么,状态就是一个变量,用以记录程序执行的情况。

    1.2 容器(Container)

    容器当然是用来装东西的,状态容器即用来存储状态的容器。状态多了,自然需要一个东西来存储,但是容器的功能却不是仅仅能存储状态,它实则是一个状态的管理器,除了存储状态外,它还可以用来对state进行查询、修改等所有操作。(编程语言中容器几乎都是这个意思,其作用无非就是对某个东西进行增删改查)

    1.3 可预测(Predictable)

    可预测指我们在对state进行各种操作时,其结果是一定的。即以相同的顺序对state执行相同的操作会得到相同的结果。简单来说,Redux中对状态所有的操作都封装到了容器内部,外部只能通过调用容器提供的方法来操作state,而不能直接修改state。这就意味着外部对state的操作都被容器所限制,对state的操作都在容器的掌控之中,也就是可预测。

    总的来说,Redux是一个稳定、安全的状态管理器

    2.为什么是Redux?

    问:不对啊?React中不是已经有state了吗?为什么还要整出一个Redux来作为状态管理器呢?

    答:state应付简单值还可以,如果值比较复杂的话并不是很方便。

    问:复杂值可以用useReducer嘛!

    答:的确可以啊!但无论是state还是useReducer,state在传递起来还是不方便,自上至下一层一层的传递并不方便啊!

    问:那不是还有context吗?

    答:的确使用context可以解决state的传递的问题,但依然是简单的数据尚可,如果数据结构过于复杂会使得context变得异常的庞大,不方便维护。

    Redux可以理解为是reducer和context的结合体,使用Redux即可管理复杂的state,又可以在不同的组件间方便的共享传递state。当然,Redux主要使用场景依然是大型应用,大型应用中状态比较复杂,如果只是使用reducer和context,开发起来并不是那么的便利,此时一个有一个功能强大的状态管理器就变得尤为的重要。

    3.什么情况使用 Redux

    首先,我们先明晰 Redux 的作用 ,实现集中式状态管理。

    Redux 适用于多交互、多数据源的场景。简单理解就是复杂

    从组件角度去考虑的话,当我们有以下的应用场景时,我们可以尝试采用 Redux 来实现

    1. 某个组件的状态需要共享时
    2. 一个组件需要改变其他组件的状态时
    3. 一个组件需要改变全局的状态时

    除此之外,还有很多情况都需要使用 Redux 来实现

    image-20221030202337038

    如上图所示,redux 通过将所有的 state 集中到组件顶部,能够灵活的将所有 state 各取所需地分发给所有的组件。

    redux 的三大原则:

    • 整个应用的 state 都被存储在一棵 object tree 中,并且 object tree 只存在于唯一的 store 中(这并不意味使用 redux 就需要将所有的 state 存到 redux 上,组件还是可以维护自身的 state )。
    • state 是只读的。state 的变化,会导致视图(view)的变化。用户接触不到 state,只能接触到视图,唯一改变 state 的方式则是在视图中触发actionaction是一个用于描述已发生事件的普通对象。
    • 使用 reducers 来执行 state 的更新。 reducers 是一个纯函数,它接受 action 和当前 state 作为参数,通过计算返回一个新的 state ,从而实现视图的更新。

    4.Redux 的工作流程

    image-20221030202728807

    如上图所示,redux 的工作流程大致如下:

    • 首先,用户在视图中通过 store.dispatch 方法发出 action
    • 然后,store 自动调用 reducers,并且传入两个参数:当前 state 和收到的 actionreducers 会返回新的 state
    • 最后,当store 监听到 state 的变化,就会调用监听函数,触发视图的重新渲染。

    5.Redux API

    5.1 store

    • store 就是保存数据的地方,整个应用只能有一个 store
    • redux 提供 createStore 这个函数,用来创建一个 store 以存放整个应用的 state
    import {
        createStore } from 'redux';
    const store = createStore(reducer, [preloadedState], enhancer);
    
    • 1
    • 2
    • 3

    createStore用来创建一个Redux中的容器对象,它需要三个参数:reducerpreloadedStateenhancer

    • reducer是一个函数,是state操作的整合函数,每次修改state时都会触发该函数,它的返回值会成为新的state。

    • preloadedState就是state的初始值,可以在这里指定也可以在reducer中指定。

    • enhancer增强函数用来对state的功能进行扩展,暂时先不理它。

    5.2 state

    • store 对象包含所有数据。如果想得到某个时点的数据,就要对 store 生成快照。这种时点的数据集合,就叫做 state
    • 如果要获取当前时刻的 state,可以通过 store.getState() 方法拿到:
    import {
        createStore } from 'redux';
    const store = createStore(reducer, [preloadedState], enhancer);
    
    const state = store.getState();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.3 action

    • state 的变化,会导致视图的变化。但是,用户接触不到 state,只能接触到视图。所以,state 的变化必须是由视图发起的。
    • action 就是视图发出的通知,通知store此时的 state 应该要发生变化了。
    • action 是一个对象。其中的 type 属性是必须的,表示 action 的名称。其他属性可以自由设置,社区有一个规范可以参考:
    const action = {
       
      type: 'ADD_TODO',
      payload: 'Learn Redux' // 可选属性
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面代码定义了一个名称为 ADD_TODOaction,它携带的数据信息是 Learn Redux

    5.4 Action Creator

    • view 要发送多少种消息,就会有多少种 action,如果都手写,会很麻烦。
    • 可以定义一个函数来生成 action,这个函数就称作 Action Creator,如下面代码中的 addTodo 函数:
    const ADD_TODO = '添加 TODO';
    
    function addTodo(text) {
       
      return {
       
        type: ADD_TODO,
        text
      }
    }
    
    const action = addTodo('Learn Redux');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • redux-actions 是一个实用的库,让编写 redux 状态管理变得简单起来。该库提供了 createAction 方法用于创建动作创建器:
    import {
        createAction } from "redux-actions"
    
    export const INCREMENT = 'INCREMENT'
    export const increment = createAction(INCREMENT)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 上边代码定义一个动作 INCREMENT, 然后通过 createAction

      创建了对应 Action Creator

      • 调用 increment() 时就会返回 { type: 'INCREMENT' }
      • 调用increment(10)返回 { type: 'INCREMENT', payload: 10 }

    5.5 store.dispatch()

    • store.dispatch() 是视图发出 action 的唯一方法,该方法接受一个 action 对象作为参数:
    import {
        createStore } from 'redux';
    const store = createStore(reducer, [preloadedState], enhancer);
    
    store.dispatch({
       
      type: 'ADD_TODO',
      payload: 'Learn Redux'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 结合 Action Creator,这段代码可以改写如下:
    import {
        createStore } from 'redux';
    import {
        createAction } from "redux-actions"
    const store = createStore(reducer, [preloadedState], enhancer);
    
    const ADD_TODO = 'ADD_TODO';
    const add_todo = createAction('ADD_TODO'); // 创建 Action Creator
    
    store.dispatch(add_todo('Learn Redux'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.6 reducer

    • store 收到 action 以后,必须给出一个新的 state,这样视图才会进行更新。state 的计算(更新)过程则是通过 reducer 实现。
    • reducer 是一个函数,它接受 action 和当前 state 作为参数,返回一个新的 state
    const reducer = function (state, action) {
       
      // ...
      return new_state;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 为了实现调用 store.dispatch 方法时自动执行 reducer 函数,需要在创建 store 时将将 reducer 传入 createStore 方法:
    import {
        createStore } from 'redux';
    const reducer = function 
    • 1
    • 2
  • 相关阅读:
    Linux 内存workingset Refault Distance算法源码及源码解析
    RHEL 7配置HAProxy实现Web负载均衡
    Hello Playwright:(3)基本概念
    Linux内存管理(十五):percpu 机制详解
    学长告诉我,大厂MySQL都是通过SSH连接的
    java计算机毕业设计高校会议室预约系统MyBatis+系统+LW文档+源码+调试部署
    把Java代理说清楚
    《从零开始的Java世界》04面向对象(高级)
    windows 查看防火墙设置命令使用方法
    计算机网络练习-计算机网络体系结构与参考模型
  • 原文地址:https://blog.csdn.net/DSelegent/article/details/127998462