redux 源码解析

111 阅读1分钟

入口文件

import createStore from "./createStore";
import combineReducer from "./combineReducer";
import bindActionCreator from "./bindActionCreator";
export {
    createStore,
    combineReducer,
    bindActionCreator
}

createStore.js

创建仓库的方法 传入 reducer 和 初始state(可不传)

export default function (reducer, initState) {
    //初始化state
    initState = initState ? initState : null;
    function getState() {
        return initState;
    }
    let listeners = [];
    function dispatch(action) {

        if(!isPlainObject(action)){
            throw new Error('action必须是一个纯对象');
        }

        if(!action.hasOwnProperty("type")) {
            throw new Error('action必须有type属性');
        }

        // 更新state
        initState = reducer(initState, action);
        // 执行listener
        for(var i = 0; i < listeners.length; i++) {
            listeners[i]()
        }
    }
    // 订阅 listener 是更新的setState
    function subscribe(listener) {
        listeners.push(listener);
        return function unsubscribe() {// 返回一个销毁的操作
            let index = listeners.indexof(listener)
            list.splice(index, 1)
        }
    }
    // 初始化执行一下dispatch  拿到 state 因为默认走的是 default
    dispatch({type: "@@redux/INIT"})
    return {
        dispatch, getState, subscribe
    }
}


export default function isPlainObject(obj){
    if(typeof obj != 'object' || obj === null){
        return false;
    }
    return Object.getPrototypeOf(obj) === Object.prototype;
}

combineReducers.js

export default function (reducers) {
    let keys = Object.keys(reducers); // 获取合并reducers 的keys {num1, num2}
    return function (state, action) {
        let currentState = {};
        for(let i = 0; i < keys.length; i++) {
            let item = keys[i]; // num1 || num2 
            let reducer = reducers[item]; // 合并其中一项reducer
            let previousState = state[item]; // 上一个状态的值
            let nextState = reducer(previousState, action); // 下一个状态值
            currentState[item] = nextState; // 返回当前key的state
        }
        return currentState;
    }

}

bindActionCreators.js

用来自动dispatch action; 这个方法会返回一个对象; 直接import bindActionCreators from './bindActionCreators'进行调用acion对象中的方法即可,就可以直接派发action,不用再次调用dispatch; egg: bindActionCreators.add

function bindActionCreator(action, dispatch) {
    return function () {
        dispatch(action.apply(this, arguments))
    }
}

export default function (actions, dispatch) {
    return function () {
        if (typeof actions === "funtion") {
            return bindActionCreator(actionCreators, dispatch);
        } else {
            let actionCreators = {};
            for (let key in actions) {
                actionCreators[key] = bindActionCreator(actions[key], dispatch);
            }
            return actionCreators;
        }
    }
}