• Redux 你懂多少?


    Redux是从Flux这个编程思想的一种实现,或者说从Flux演变而来,同时还做了些封装和变换,让开发者更容易对前端应用状态进行管理和维护。由于Redux的成功,也逐渐演化出其他的一些类似框架,如mobx,vuex等等。

    很多人喜欢说Redux接入之后,就是MC*框架了,我个人理解是,这个就是一个很好用的状态管理,和MVC或者MVVM等框架没有必然联系,思路也不完全一致,没必要非要定义出它是谁和它不是谁的结论出来,只要引入这个框架之后,我们的应用扩展性变好了,维护性,可测试性,等程序架构设计的指标变的更好了,就是合适当前项目的好框架。

    今天我们主要谈一谈它与React的结合,Redux也成了React状态管理的御用框架,在目前(2020年)算是最主流的,当然React还可以与其他框架合作,如GraphQL,mobx等框架,并没有强制绑定。同时React项目也可以不与任何状态管理框架集成,但随着大型前端项目复杂度的增加,过多的业务逻辑,处理流程糅合在一起,就会出现职责不单一,交互困难,维护成本过高等问题,所以中大型项目还是需要一个 "专业" 的tool来帮忙。

    Redux的核心流程是怎么样的呢?

    1. dispatch( action) ==>  reducers 处理得到新的state ==》store 去通知监听者响应变化。

    本质来说,就是一种观察者模式,观察者(component)通过拉(pull)模式从store的全量state中选取出自己需要关注的子state作为props传递给展示组件进行渲染,它是一种单向数据流方式。

    redux最核心的估计就是createStore()方法,简要记录几点

    了解下方法的基本结构

    //简易核心实现    
    const createStore = (reducer) => { let state; let listeners = []; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); }; const subscribe = (listener) => { listeners.push(listener); return () => { listeners = listeners.filter(l => l !== listener); } };
    // 这里初始化dispatch的原因是在这之前,state是为null的
    //所以我需要传一个不存在的action去reducer里面,拿到最默认的那个defaultState,这个defaultState写在reducer的那个文件里面
    dispatch({});
    return { getState, dispatch, subscribe }; };
    function(reducer, preloadedState, enhancer){
    
    let currentReducer = reducers;
    
    let currentState = preloadedState;
    
    let currentListeners = [];
    
    let isDispatching = false; //这个全局变量主要用于dispatch action时,不允许多个同时action同时触发,强制同步。
    
    // some codes to define core function.
    
    return {
    
    dispatch,
    
    getState,
    
    subscribe,
    
    replaceReducer
    
    } 
    
    }

    2. listeners 数组里面放的是什么?

    其实源码分析发现,它都是function,当store中的action触发reducers得到新的state后,store通过forEach 遍历所有listener执行.

    那这个function怎么通知到我们的component呢?

    是在react-redux 核心方法 connect中 ,通过provider传递给容器组件的context---store,store.subscribe(func), 这个func会push到listeners这个数组中。那这个func是什么?实际上操作容器组件的state的方法,react 组件中,state变化,则会导致重新渲染,也就会导致被包装组件的重新渲染。

    3. createStore 方法里面维护了几个闭包?

    a. 一个是currentReducers,这个就可以让store支持热替换reducers,store.replaceReducer()。

    b. currentState, 这个是store的单一唯一的全局数据对象,单一store,单一的state,通过getState获取。通过(prevState, action) => newState,对这个变量修改

    c. listeners, 这个是数组,存放所有的观察者注入进来的方法,当state变化时,调用这些方法,这些方法会去修改component的state,从而触发组件树的更新。

    4. 几个Redux源码片段

    function dispatch(action) {
        if (!isPlainObject(action)) {
          throw new Error(
            'Actions must be plain objects. ' +
              'Use custom middleware for async actions.'
          )
        }
     
        if (typeof action.type === 'undefined') {
          throw new Error(
            'Actions may not have an undefined "type" property. ' +
              'Have you misspelled a constant?'
          )
        }
     
        if (isDispatching) {
          throw new Error('Reducers may not dispatch actions.')
        }
     
        try {
          isDispatching = true
          currentState = currentReducer(currentState, action)
        } finally {
          isDispatching = false
        }
     
        const listeners = (currentListeners = nextListeners)
        for (let i = 0; i < listeners.length; i++) {
          const listener = listeners[i]
          listener()
        }
     
        return action
      }
    function subscribe(listener) {
        let isSubscribed = true
     
        ensureCanMutateNextListeners()
        nextListeners.push(listener)
     
        return function unsubscribe() {
          if (!isSubscribed) {
            return
          }
     
          if (isDispatching) {
            throw new Error(
              'You may not unsubscribe from a store listener while the reducer is executing. ' +
                'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
            )
          }
     
          isSubscribed = false
     
          ensureCanMutateNextListeners()
          const index = nextListeners.indexOf(listener)
          nextListeners.splice(index, 1)
        }
      }
     function getState() {
        return currentState
      }
  • 相关阅读:
    Integer判等的陷阱:你知道Integer内部高速缓冲区IntegerCache吗?
    Unicode 是不是只有两个字节,为什么能表示超过 65536 个字符
    java中Char到底是什么格式的编码
    Java中char和String 的深入理解
    关于serialVersionUID的说明
    Java中的instanceof和isInstance基础讲解
    编码(1)学点编码知识又不会死:Unicode的流言终结者和编码大揭秘
    知识图谱和图卷积(贪心学院)——学习笔记
    索尼相机,索尼W35,Sony Cyber-shot DSC-w35
    高斯分布与高斯过程梳理
  • 原文地址:https://www.cnblogs.com/roy1/p/13844670.html
Copyright © 2020-2023  润新知