zoukankan      html  css  js  c++  java
  • 学习Redux之分析Redux核心代码分析

      1. React,Flux简单介绍

      学习React我们知道,React自带View和Controller库,因此,实现过程中不需要其他任何库,也可以独立开发应用。但是,随着应用程序规模的增大,其需要控制的state也会越来越多,为了统一控制,我们一般都会将所有的状态和控制逻辑都放在顶层组件中,这样就会导致,react顶层组件中体积庞大,并且数据和组件混合在一起,非常不方便管理。

      在这种情况下Flux,就出现了,他提出了将应用程序,分为三部分:dispatcher storeview。其中,dispatcher负责分发事件;store负责保存数据,同时响应事件并更新数据;view负责订阅store中的数据,根据数据渲染相应的页面,并提供用户交互。

      实际上来说,从React到Flux,我们只是将我们React中定义的顶层组件中数据与逻辑拆分到不同的文件中:

      1. 将state写在store中,在store 中存放数据,并向外提供一个getter接口,为state提供唯一数据接口;并创建change事件注册函数;

      2. 将合成事件的回调函数,转化成action对象(js对象,具有一个type属性,用于表示action的类型,并通过payload属性传递数据),并使用Dispatcher对象中的dispatch方法将事件对象分发出去。

      3. 利用dispatcher对象中提供的register方法,注册action,接收dispatch方法分发action对象,对store的数据进行相应操作,并触发change事件;

      4. 我们在组件中监听自定义change事件,当监听到change事件,重新获取store中的数据 ,设置state,重新渲染页面。

      实际上Flux并不是一个框架,而是前端应用架构,它提出了单向数据流,可以提供清晰的数据流。同时将数据和组件分离,使应用程序结构更清晰。但是flux依旧存在一些问题。

      Redux,利用Flux提出的架构思想和少量的核心代码,方便了我们的开发。以上都是简单介绍,下面通过Redux核心代码,其中部分都是简化代码。

      2. Redux核心代码介绍

      1. createStore方法

      下面代码是createStore的简单实现,其中保留了其中三个主要的方法getState,dispatch,subscribe实现,省略了参数处理部分,和一些其他方法实现。

    // createStore方法简单实现

    const createStore = (reducer) => {

      // 定义state,监听器数组   let state;   let listeners
    = [];   
      // 定义getter方法,唯一一个获取数据的接口   const getState
    = () => state;
      // 定义dispatch方法,用户分发action事件,接收一个action对象,生成新的state,并通知所有监听器   const dispatch
    = (action) => {
        // 利用reducer生成新的state     state
    = reducer(state, action);
        // 通知所有监听器,调用回调函数     listeners.forEach(listener
    => listener());   };   
      // 定义subscribe方法,注册监听器,并返回一个用于取消当前注册监听器的函数,用于取消监听 
      const subscribe
    = (listener) => {
        // 添加到监听数组中     listeners.push(listener);
        // 返回取消监听函数     
    return () => {       listeners = listeners.filter(l => l !== listener);     }   };
      // 调用dispatch,初始化state   dispatch({});
      // 返回getState,dispatch,subscribe三个方法
      return { getState, dispatch, subscribe }; };

      我们从上面代码可以知道,createStore接收一个reducer函数参数,每次调用dispatch函数,利用reducer函数,以及之前的state,以及action,计算出最新的state,并通知所有的监听器,通过调用getState方法,调用最新的state。同时组件通过subscribe函数,注册一个监听器,从而每当数据更新时,通知监听组件。

      以上就是Redux中最主要的createStore对象中主要方法介绍。

      2. combineReducers函数

      reducer函数,其实就是根据当前的state和action,计算出一个新的state,之所以叫reducer,是因为它的功能就是action对象数组调用reduce函数,产生最新的状态。

      当我们的应用程序规模非常大时,我们需要将reducer进行拆分,我们可以直接自定义一个总的合并reducer,也可以使用conbineReducers函数来合并,最终效果等价。

    // 合并多个reducer
    // 返回一个合并的reducer函数,接收两个参数state和action
    /**
     * combineReducers调用方法
     * combineReducers({
     *     a: a,
     *     b: b,
     *     c: c
     * }); 
     * 等价于
     * {
     *     a: a(state.a, action),
     *     b: b(state.b, action),
     *     c: c(state.c, action)
     * }
     */
    const combineReducers = reducers => {
        return (state = {}, action) => {
            // 获取所有自身可枚举属性,并进行reduce操作,
            // 将合并在一起,初始值为空数组
            return Object.keys(reduers).reduce(
                (nextState, key) => {
                    nextState[key] = reducers[key](state[key], action);
                    return nextState;
                }, {}
            );
        };
    };

      3. applyMiddleware函数

      该函数是在当createStore函数传入applyMiddleware参数时,在createStore中调用的。其实createStore函数的实际参数有三个reducer, preloadedState(state默认值), enhancer, 并且在函数中一些了参数判断,主要就是,将enhancer(在这里是applyMiddleware函数) 参数进行匹配,如果createStore参数中具有enhancer, 则直接调用enhancer(createStore)(reducer, preloadedState)对store进行初始化。

      其中applyMiddleware中有调用createStore函数,来初始化store,然后用middleware对初始化的store 中的dispatch函数进行包装,得到最终增强的applyMiddleware,最终返回具有增强的applyMiddleware的store。

    // 将中间件和store.dispatch组合
    // 返回具有整合后的dispatch方法的store
    
    /**/
    
    export default function applyMiddleware(...middlewares) {
        return (createStore) => (reducer, preloadedState, enhancer) => {
            // 根据上面分析,reducer,preloadedState即为createStore中的reducer,preloadedState
            // enhancer为空
            
            // 创建一个初始化的store,基本逻辑即为上面createStore函数分析
            var store = createStore(reducer, preloadedState, enhancer);
            // 获取此时dispatch函数副本
            var dispatch = store.dispatch;
            // 用于存放中间件函数数组
            var chain = [];
    
            // 中间件的执行参数,中间件编写规定
            var middlewareAPI = {
                getState: store.getState,
                dispatch: (action) => dispatch(action)
            };
    
            // 对每一个中间件进行处理后存放
            chain = middlewares.map(middleware => middleware(middlewareAPI));
            // 使用compose函数,将处理后的中间件,和dispatch进行合并,得到增强后的dispatch
            // 如果chain为[f1, f2, f3],那么dispatch经过compose处理后为 f1(f2(f3(dispatch)))
            dispatch = compose(...chain)(store.dispatch);
    
            // 将增强后的dispatch,赋值给store,并返回store
            return {...store,
                dispatch
            }
        }
    }

      其中的compose函数,主要就是利用了reduceRight函数对参入的参数进行了处理,就不详细说明了。

      我想大家如果了解了上面这些,就能容易理解Redux如何工作的了。

  • 相关阅读:
    Vue Supermall蘑菇街API后端接口
    Vue UI库:ElementUI使用教程
    Python操作数据库,读取数据并按照json格式写入json文件
    css 轮播图
    ArcGIS Server密码重置
    JavaScript之箭头函数
    arcgis属性对比
    JavaScript之Promise
    很遥远
    请不要等到四十年后才明白
  • 原文地址:https://www.cnblogs.com/diligentYe/p/6648434.html
Copyright © 2011-2022 走看看