本文redux源码主要围绕从一个stroe的创建到所有核心API充分利用运行的角度来分析

    createStore

    • createStore是redux的核心,主要方法有getState、dispach、subscribe
    • createStore的主要功能就是创建store,处理View对action的触发,完成reduce返回新的state值进行保存以及更新store状态

    创建store
    createStore主要接收3个参数:reduce, preloadState, enhancer.

    • reduce是外部传入触发action以后的逻辑处理方法
    • preloadState是默认的state
    • enhancer如词本意,就是用于增强store

    createStore函数通过接收preloadState作为currentState默认值,View可以通过getState获取currentState状态,然后通过dispatch调用readuce处理action触发的逻辑并返回一个新的state用currentState保存起来.最后用subscribe方法订阅store,当store状态发生改变的时候可以获取最新的store状态并进行逻辑处理

    如下图所示:

    1. // 建立redux模型
    2. function createStore(reduce, preloadState, enhancer) {
    3. //接收默认state
    4. let currentState = preloadState
    5. //订阅队列
    6. let curentListeners = [];
    7. // 获取状态
    8. function getState() {
    9. return currentState
    10. }
    11. // 触发action
    12. function dispatch(action) {
    13. //处理reduce
    14. currentState = reduce(currentState, action)
    15. //每一个订阅者都可以通过此回调获取最新store
    16. for (let i = 0; i < curentListeners.length; i++) {
    17. let listener = curentListeners[i];
    18. listener()
    19. }
    20. }
    21. //订阅状态
    22. function subscribe(listener) {
    23. curentListeners.push(listener)
    24. }
    25. // 返回所有的核心方法
    26. return {
    27. getState,
    28. dispatch,
    29. subscribe,
    30. }
    31. }

    createStore添加参数约束
    为了避免开发者调用的出现类型错误导致的页面崩溃,一般的底层代码都会做类型判断处理,针对reduce做了一个简单的是否为函数判断处理
    isPlainObject函数是用来判断action是否为对象的处理函数,因为action有可能传入null 或者是对象和数组,单纯的判断是否为object已经不能区分数组了,我们通过Object.getPrototypeOf方法查找上一级的逻辑运算,直到找到最上一级再与obj本身对比..如果全等就是对象

    如下图所示:

    1. // 建立redux模型
    2. function createStore(reduce, preloadState, enhancer) {
    3. let currentState = preloadState
    4. let curentListeners = [];
    5. // 判断reduce是否为函数
    6. if (typeof reduce !== "function") {
    7. throw Error("reduce 必须是一个函数")
    8. }
    9. ....
    10. // 触发action
    11. function dispatch(action) {
    12. // 判断action是否为对象
    13. if (!isPlainObject(action)) throw Error("action 必须是一个对象");
    14. if (typeof action.type === "undefined") throw Error("action 必须有type属性");
    15. currentState = reduce(currentState, action)
    16. for (let i = 0; i < curentListeners.length; i++) {
    17. let listener = curentListeners[i];
    18. listener()
    19. }
    20. }
    21. // 返回所有的核心方法
    22. return {
    23. getState,
    24. dispatch,
    25. subscribe,
    26. }
    27. }
    28. // 判断是否为对象
    29. function isPlainObject(obj) {
    30. // 非对象或为空直接返回false
    31. if (typeof obj !== "object" || obj === null) return false
    32. // 区分数组和对象
    33. let proto = obj
    34. // 循环查找上一级直到没有为止
    35. while (Object.getPrototypeOf(proto) !== null) {
    36. proto = Object.getPrototypeOf(proto)
    37. }
    38. // 如果最后一级跟第一级相等,则为对象
    39. return proto === Object.getPrototypeOf(obj)
    40. }

    Enhancer
    Enhancer是用于增强createStore,可以让createStore的调用者对返回Store对象进行功能上的增强(类似于thunk,saga等插件的增强效果)
    Enhancer的基本逻辑其实很简单,就是通过判断action的类型来处理,总共两种情况:

    1. action是函数,此时调用action方法传入disptch函数(外部操作执行完成之后利用返回的dispathc参数继续调用dispatch方法)
    2. action是对象则是正常调用dispatch方法传入action即可

    代码如下图所示:

    1. // 建立redux模型
    2. function createStore(reduce, preloadState, enhancer) {
    3. ....
    4. // 判断enhancer是否为空
    5. if (typeof enhancer !== "undefined") {
    6. if (typeof enhancer !== "function") {
    7. throw Error("enhancer 必须是一个函数")
    8. }
    9. // 调用enhancer传入state和reduce
    10. return enhancer(createStore)(reduce, preloadState)
    11. }
    12. ....
    13. // 返回所有的核心方法
    14. return {
    15. getState,
    16. dispatch,
    17. subscribe,
    18. }
    19. }
    20. // action逻辑处理函数(中间件)
    21. function enhancer(createStore) {
    22. return function (reduce, preloadState) {
    23. const store = createStore(reduce, preloadState)
    24. let dispatch = store.dispatch
    25. function _dispatch(action) {
    26. if (typeof action === "function") {
    27. // action(dispatch)
    28. return action(dispatch)
    29. }
    30. dispatch(action)
    31. }
    32. return {
    33. ...store,
    34. dispatch: _dispatch
    35. }
    36. }
    37. }

    applymiddleware

    • applymiddleware本质上跟enhancer的性质相同,都是为了增强dispatch的能力
    • applymiddleware是redux为了处理单个或多个中间件组合的函数,让中间件按照顺序依次执行,当View上触发了action之后会先被中间件接收到,经过一个或者多个的中间件处理之后,action才会被传递给reduce进行处理

    具体代码如下图所示:

    1. // 处理中间件
    2. function applymiddleware(...middlewares) {
    3. return function (createStore) {
    4. return function (reduce, preloadState) {
    5. // 创建Store
    6. const store = createStore(reduce, preloadState)
    7. // 用于中间件处理的store
    8. const StoreAPI = {
    9. dispatch: store.dispatch,
    10. getState: store.getState,
    11. }
    12. const chain = middlewares.map(middleware => middleware(StoreAPI))
    13. //得到第一层的中间件方法
    14. let dispatch = compose(...chain)(store.dispatch)
    15. return {
    16. ...store,
    17. dispatch: dispatch
    18. }
    19. }
    20. }
    21. }
    22. // 处理中间件的函数嵌套
    23. function compose() {
    24. var funcs = [...arguments];
    25. return function (dispatch) {
    26. // 反推loger(也就是上一层中间件)的next参数,其实就是最后一层thunk的最后一层函数
    27. for (var i = funcs.length - 1; i >= 0; i--) {
    28. dispatch = funcs[i](dispatch)
    29. }
    30. return dispatch;
    31. }
    32. }

    bindActionCreatetors

    • bindActionCreatetors的主要用途是将ActionCreatetor函数转换为能够触发action的函数
    • bindActionCreatetors有2个参数第一个是ActionCreatetor函数对象,包含了单个或者多个ActionCreatetor函数,第二个是dispatch,用于触发action

    bindActionCreatetors具体实现代码如下:

    // bindActionCreatetors函数实现
    function bindActionCreatetors(ActionCretors, dispatch) {
          //用于保存要触发action
        let bindActionCreatetorsobj = {};
        for (let i in ActionCretors) {
            bindActionCreatetorsobj[i] = () => {3
                dispatch(ActionCretors[i]())
            }
        }
        return bindActionCreatetorsobj;
    }
    

    combineReducers

    • 用于组合reduce,将零碎的小reduce组合起来变成一个大的reduce
    • 便于管理reduce零碎的state状态

    代码如下图所示:

    // 组合小的reduce成一个大的reduce
    function combineReducers(reducers) {
        // 判断每一个reduces的类型必须为函数
        let reducerKeys = Object.keys(reducers)
        for (let i = 0; i <= reducerKeys.length - 1; i++) {
            let key = reducerKeys[i]
            if (typeof reducers[key] !== "function") throw Error("reduce必须是一个函数")
        }
    
        return function (state, action) {
            //state对象,用于存储每个reduce的值
            var nextState = {};
            for (var i = 0; i < reducerKeys.length; i++) {
                var key = reducerKeys[i];
                var reducer = reducers[key];
                var previousStateForKey = state[key];
                  //拿到最新的state值
                nextState[key] = reducer(previousStateForKey, action)
            }
              //返回最新的state状态对象
            return nextState;
        }
    }
    

    本文源代码以及编写流程:https://gitee.com/xielingyun879475908/my-redux