Redux从入门到进阶

redux简介

redux 是一个三方通用的状态管理库,它采用单一集中化的state和发布订阅者模式,通过dispatch action事件管理状态。

核心概念

store:状态容器,用于状态的存储和管理。

dispatch:事件派发函数,触发reducer更新状态

action:更新事件,通常是一个带有type属性的对象

基本工作流程

  • 创建状态管理仓库:createState 接收reducer、preloadState和 enhancer,返回状态仓库对象(store)。
    • reducer是一个函数,接收当前state和action,返回新的state。新的state需要是一个新的对象,state应遵循不可变更新原则。
    • preloadState 是一个对象,用于初始化状态。通常用于状态持久化等操作
    • enhancer 是一个函数,用于增强状态管理。可以通过Redux提供的applyMiddleware增强器,也可以通过第三方提供的增强器增强store的能力
    • store 是一个对象,向外提供状态仓库访问(getState)、更新(dispatch)和订阅(subscribe)等方法
  • 使用状态:通过store对象上的getState方法访问state。可以将取值器传入getState,精确的获取状态。
  • 更新状态:通过store对象上的dispatch方法派发更新,dispatch接收action,调用reducer并将action传入。
  • 订阅更新:通过store对象上的subscribe方法订阅更新,当state发生变化时(Object.is判断),通知订阅者。

高级应用

combineReducers:在redux的实际使用中,通过单个reducer管理状态的更新逻辑会让代码量变得非常的庞大和难以维护。我们可以创建多个reducer,每个reducer负责单个模块的更新逻辑。通过 combineReducers 辅助函数组合这些reducer。combineReducers 接收reducers对象,返回组合后的reducer,并在state上添加reducers的key,指向reducer返回的state。

  1. Reducer的拆分和组合

    php 复制代码
    function countReducer(state=preloadState, action) {
      switch (action.type) {
        case 'INCREMENT':
          return { ...state, count: state.count + 1 };
        case 'DECREMENT':
          return { ...state, count: state.count - 1 };
        default:
          return state;
      }
    }
    function userReducer(state=userInfo , action) {
      switch (action.type) {
        case 'SET_USER':
          return { ...state, user: action.user};
        default:
          return state;
      }
    }
    
    const preloadState = { count: 0 };
    const userInfo = { user: '' };
    const store = createStore(combineReducers({
      count: countReducer,
      user: userReducer,
    }));

enhancer:store功能增强。applyMiddleware是redux唯一内置的store增强器。

  1. 增强器的实现原理和基本使用如下

    javascript 复制代码
    //创建增强器,增强器接收createStore,返回新的createState
    //(nextCreateStore) => StoreCreator
    function autoEnhancer(next) {
      return (reducer, preloadState) => {
        console.log(next)
        const store = next(reducer, preloadState);
        return {
          ...store,
          consoleMsg: (msg: string) => msg,
        };
      }
    }
    
    //创建Store
    createStore(reducer, proloadState, enhancer)
    
    //createStore的实现大致如下
    function createStore(reducer, preloadState, enhancer) {
      //如果有增强器,就用增强器创建store
      if (enhancer) {
        return enhancer(createStore)(reducer, preloadState);
      }
      //如果没有增强器,就用默认的createStore创建store
      const state = reducer(preloadState, { type: '@@redux/INIT' });
      return {
        dispatch: (action) => {
          state = reducer(state, action);
        },
        getState: () => state,
      }
    }

    通过上面增强器的基本原理,就可以对原store添加额外的能力,对store增强。

  2. 多增强器的使用。Redux提供了compose函数用于多增强器场景代码组织,如下:

    javascript 复制代码
    //创建增强器
    function autoEnhancer(next) {
      return (reducer, preloadState) => {
        console.log(next)
        const store = next(reducer, preloadState);
        return {
          ...store,
          consoleMsg: (msg: string) => msg,
        };
      }
    }
    function autoEnhancer2(next) {
      return (reducer, preloadState) => {
        const store = next(reducer, preloadState);
        return {
          ...store,
          consoleMsg2: (msg: string) => (`consoleMsg2: ${msg}`),
        };
      }
    }
    
    //创建store。compose会将所有的增强器从右往左调用,最终组合成为一个增强器返回
    const store = createStore(countReducer, preloadState, compose(autoEnhancer, autoEnhancer2));
    //compose的内部核心原理
    function compose(...enhancers) {
      //传给第一个增强器的createStore函数传递给最后一个增强器,将下一个增强器返回的结果作为参数传递给上一个增强器。最终返回一个增强器
      return enhancers.reduce((prev, next) => (...args) => next(prev(...args)));
    }
  3. applyMiddleware API的作用及原理。applyMiddleware的作用是对store的dispatch增强,允许在dispatch在到达reducer之前,做一些其他的任务处理,其基本实现如下:

    javascript 复制代码
    function applyMiddleware(...middlewares){
      return createStore => (reducer, preloadedState) => {
        const store = createStore(reducer, preloadedState);
        let dispatch: Dispatch = () => {
          throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');
        };
        const middlewareAPI: MiddlewareAPI = {
          getState: store.getState,
          dispatch: (action, ...args) => dispatch(action, ...args)
        };
        const chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose<typeof dispatch>(...chain)(store.dispatch);
        return {
          ...store,
          dispatch
        };
      };
    }

    结合redux middleware的使用,一步步剖析其执行过程,如下:

    javascript 复制代码
    //创建middleware
    const logMiddleware = function({ getState, dispatch }) {
      return next => action => {
        console.log("console");
        const result = next(action);
        return result;
      }
    }
    const alertMiddleware = function({ getState, dispatch }) {
      return next => action => {
        console.log("alert");
        const result = next(action);
        return result;
      }
    }
    
    //使用中间件
    const store = createStore(countReducer, preloadState, applyMiddleware(logMiddleware, alertMiddleware));
    
    //applyMiddleware的本质是一种store增强,所以applyMiddleware遵循增强器的声明规则,对于上述applyMiddleware中增强器的执行过程不做剖析。
    //1、创建中间件链
    const chain = middlewares.map(middleware => middleware(middlewareAPI));
    //chain的结构是这样的
    [
    next=> action => {
      console.log("console");
      const result = next(action);
      return result;
    },
    next=> action => {
      console.log("alert");
      const result = next(action);
      return result;
    },
    ]
    //2、组合中间件链
    let dispatch = compose<typeof dispatch>(...chain)(store.dispatch);
    //它等同于下面的代码
    let dispatch = chain.reducer((prev, next) => (...args) => prev(next(...args)))(store.dispatch);
    //重写后的dispatch函数如下
    action => {
      console.log("console");
      const result = action => {
        console.log("alert");
        const result = store.dispatch(action);
        return result;
      };
      return result;
    }

中间件:对dispatch的能力增强。在上文【applyMiddleware API的作用及原理】中其实已经梳理了中间件的定义、挂载和整个工作流程的原理。可以看出,增强器和中间件是不同的:首先是在功能上面的区别,增强器是对store能力的扩展 ,而中间件是在dispatch到reducer过程中添加新的能力。导致在签名上也存在区别,增强器接收createStore,返回新的createStore,增强器通过compose组合成为一个增强器后提供给createStore;中间件则遵循({getStore, dispatch})=>next=>action => result函数签名。中间件需要通过redux提供的唯一增强器applyMiddleware注册到store,在applyMiddleware内部会将多个中间件组合成为一个dispatch。

相关推荐
云枫晖3 小时前
JS核心知识-闭包
前端·javascript
前端老鹰3 小时前
HTML `<meter>` 标签:原生度量衡指示器,直观展示百分比、评分等量化数据
前端·html
赵明飞3 小时前
如何配置GDO51和GDI51网关通过Basic Station连接到ChirpStack平台
前端
前端康师傅3 小时前
Javascript 数组基础用法
前端·javascript
胖鱼罐头3 小时前
Android-尺寸单位换算全解析
前端
召摇3 小时前
命令-查询分离原则(Command-Query Separation)
前端·javascript·面试
不一样的少年_3 小时前
别再无脑装插件了!你的浏览器扩展可能正在“偷家”
前端·安全·浏览器
猪哥帅过吴彦祖3 小时前
第 3 篇:让图形动起来 - WebGL 2D 变换
前端·javascript·webgl
Linsk3 小时前
如何实现TypeScript级的polyfill自动引入
前端·typescript·前端工程化