Skip to content

redux插件原理详解 #16

@luke93h

Description

@luke93h

前言

redux本身代码量十分精简,出去注释,代码量也就100多行,大部分逻辑页非常好动。唯一有点难处的就是它的插件机制。

本文目标便是帮助给为彻底理解redux的插件机制

背景

  1. 本文介绍基于redux-4.0.0
  2. 本文分析源码的源码文件为:

使用方法

import { createStore, applyMiddleware } from 'redux'
import reducer from './reducers'
import middleware from './middleware'

function logger(store) {
  return (next) => (action) => {
    let returnValue = next(action)
    return returnValue
  }
}

let store = createStore(
  reducer,
  [ 'Use Redux' ],
  applyMiddleware(middleware)
)

可以看到createStore接受三个参数,第一个参数为reducer,第二个参数为state的初始值,第三个参数为enhancer。

接下来就让我们从createStore走进middleware。

createStore

createStore(reducer, preloadedState, enhancer) {

  // enhancer必须为函数,直接返回由enhancer生成的store
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }

    return enhancer(createStore)(reducer, preloadedState)
  }

  ...
}

可以看到一旦给createStore传入enhancer后,整个store都将由enhancer来生成,接下来我们来走进redux应用插件的enhancer,也就是前面的applyMiddleware(middleware)

applyMiddleware

import compose from './compose'

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    // 通过传进来的createStore生成store
    const store = createStore(...args)
    // 构建middleware期间禁止调用dispatch
    let dispatch = () => {
      throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
          `Other middleware would not be applied to this dispatch.`
      )
    }
    // 将要传给middleware的api
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    // 此处传入store
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

以上就是applymiddleWare的全部代码了,最后再来了解下compose

compose

function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }
  // 注册时从左往右执行,
  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

嗯,没错compose的代码更少,如果middleWare为[fn1, fn2, fn3],则compose后的顺序为fn1(fn2(fn3(dispatch)))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions