学习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如何工作的了。

posted @ 2017-03-31 10:23  勤劳的小叶酱  阅读(716)  评论(1编辑  收藏  举报