认识 Redux

为什么需要 Redux

  1. JavaScript 开发的应用程序,已经变得越来越复杂了:
    1. JavaScript 需要管理的状态越来越多,越来越复杂;
    2. 这些状态包括服务器返回的数据、缓存数据、用户操作产生的数据等等,也包括一些 UI 的状态,比如某些元素是否被选中,是否显示加载动效,当前分页;
  2. 管理不断变化的 state 是非常困难的:
    1. 状态之间相互会存在依赖,一个状态的变化会引起另一个状态的变化,View 页面也有可能会引起状态的变化;
    2. 当应用程序复杂时,state 在什么时候,因为什么原因而发生了变化,发生了怎么样的变化,会变得非常难以控制和追踪;
  3. React 是在视图层解决了 DOM 的渲染过程,但是 State 依然是需要自己来管理:
    1. 无论是组件定义自己的 state,还是组件之间的通信通过 props 进行传递;也包括通过 Context 进行数据之间的共享;
    2. React 主要负责帮助我们管理视图,state 如何维护最终还是我们自己来决定;
  4. Redux 就是一个帮助管理 State 的容器ReduxJavaScript 的状态容器,提供了可预测的状态管理;

Redux 基本概念

  1. State:应用程序中存储数据的地方,它是一个对象,包含整个应用程序的状态;

  2. Action:定义应用程序中发生的操作的对象,它是一个简单的 JavaScript 对象,包含一个 type 属性和一些其他数据;

  3. ReducerRedux 中管理 state 的函数,每个 reducer 负责处理一个特定的部分的 state,并返回一个新的 state

  4. StoreRedux 中的核心对象,它负责保存整个应用程序的 state,并提供一些方法来访问和更新 state

Redux 三大原则

  1. 单一数据源:整个应用程序的 state 被存储在一颗 object tree 中,并且这个 object tree 只存储在一个 store 中:

    1. Redux 并没有强制不能创建多个 Store,但是那样做并不利于数据的维护;
    2. 单一的数据源可以让整个应用程序的 state 变得方便维护、追踪、修改;
  2. State 是只读的:唯一修改 State 的方法一定是触发 action,不要试图在其他地方通过任何的方式来修改 State

    1. 这样就确保了 View 或网络请求都不能直接修改 state,它们只能通过 action 来描述自己想要如何修改 state
    2. 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心 race condition (竟态) 的问题;
  3. 使用纯函数来执行修改:通过 reducer 将旧 stateactions 联系在一起,并且返回一个新的 State

    1. 随着应用程序的复杂度增加,可以将 reducer 拆分成多个小的 reducers,分别操作不同 state tree 的一部分;
    2. 但是所有的 reducer 都应该是纯函数,不能产生任何的副作用;

Redux 基本使用

Redux 结构划分

  1. 安装 redux

    npm install redux --save
    
  2. 创建一个新的项目文件夹:learn-redux

    npm init
    
  3. 修改 package.json 可以执行 index.js

    "scripts": {
      "start": "node src/index.js"
    }
    
  4. redux 结构进行划分

    JavaScript
    JavaScript
    JavaScript
    JavaScript
    JavaScript
    // store/index.js
    import * as redux from "redux";
    import reducer from "./reducer.js";
    
    const store = redux.createStore(reducer);
    
    export default store;
    
    // store/actionCreators.js
    import { ADD_NUMBER, SUB_NUMBER } from "./constants.js";
    
    const addAction = (count) => ({
      type: ADD_NUMBER,
      num: count,
    });
    
    const subAction = (count) => ({
      type: SUB_NUMBER,
      num: count,
    });
    
    export { addAction, subAction };
    
    // store/reducer.js
    import { ADD_NUMBER, SUB_NUMBER } from "./constants.js";
    
    const initialState = {
      counter: 0,
    };
    
    function reducer(state = initialState, action) {
      switch (action.type) {
        case ADD_NUMBER:
          return { ...state, counter: state.counter + action.num };
        case SUB_NUMBER:
          return { ...state, counter: state.counter - action.num };
        default:
          return state;
      }
    }
    
    export default reducer;
    
    // store/constants.js
    const ADD_NUMBER = "ADD_NUMBER";
    const SUB_NUMBER = "SUB_NUMBER";
    
    export { ADD_NUMBER, SUB_NUMBER };
    
    // src/index.js 测试
    import store from "./store/index.js";
    import { addAction, subAction } from "./store/actionCreators.js"
    
    // 订阅store的变化,当状态更新时,会调用这个函数
    store.subscribe(() => {
      console.log(store.getState());
    });
    
    // 发起一个 action 更新状态
    store.dispatch(addAction(1)); // 输出:1
    store.dispatch(addAction(1)); // 输出:2
    store.dispatch(subAction(1)); // 输出:1
    

Redux 流程图

  1. 全局通常只有一个 Store 存储 State

  2. Component 中在某些情况会派发 Action (这些 Action 是提前定义好的)

  3. Reducer 会接收到这些 Action,并且在 Reducer 中会返回一个新的 State,作为 StoreState

  4. State 发生更新之后会触发通知,告知订阅者数据发生了改变;

  5. 订阅者拿到最新的数据 (在 props 中),更新到 jsx 中,界面发生改变;

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 认识 Redux
    1. 1.1. 为什么需要 Redux
    2. 1.2. Redux 基本概念
    3. 1.3. Redux 三大原则
  2. 2. Redux 基本使用
    1. 2.1. Redux 结构划分
    2. 2.2. Redux 流程图