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
  }

 

posted @ 2020-10-20 09:27  lswtianliang  阅读(112)  评论(0编辑  收藏  举报