1

一、Redux的功能是什么?

  • 将状态统一放在一个state中,由store来管理这个state
  • 这个store按照reducer的“shape”(形状)创建。
  • reducer的作用是接收到action后,输出一个新的状态,对应地更新store上的状态。
  • 根据redux的原则指导,外部改变state的最佳方式是通过调用store的dispatch方法,触发一个action,这个action被对应的reducer处理,完成state更新。
  • 可以通过subscribe在store上添加一个监听函数。每当调用dispatch方法时,会执行所有的监听函数。
  • 可以添加中间件(middleware)处理副作用。

这个过程中,Redux需要提供的功能是:

  • 创建store,即:createStore( )
  • 创建出来的store提供subscribe,dispatch,getState,replaceReducer这些方法
  • 将多个reducer合并为一个reducer,即:combineReducers( )
  • 应用中间件,即applyMiddleware( )

二、Redux源码结构

这就是Redux的源码结构:
image
这里有上面所说的applyMiddleware.ts、combineReducers.ts、createStore.ts,至于compose.ts和bindActionCreators.ts则是一些工具,后面会讲到。

1.compose.ts

其实说白了,compose( )这个函数的作用就是:

const func = [f1, f2, f3];
compose(...func)        //return f1(f2(f3(...args)))
//注意函数调用的顺序是从左到右,即:f1 -> f2 -> f3

下面是compose( )的源码:

export default function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return <T>(arg: T) => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}

其实换成这样更好理解:

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

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

其实最关键就是这句话:

return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));

reduceRight( )就是reduce( )的倒序执行,也就是reduce( )是从左到右执行,reduceRight( )是从右到左执行

2.createStore.ts

这个函数大致是这样的:

function createStore(reducer, preloadedState, enhancer) {
    if (typeof enhancer !== 'undefined') {
      if (typeof enhancer !== 'function') {
        throw new Error('Expected the enhancer to be a function.')
      }

      return enhancer(createStore)(
        reducer,
        preloadedState as PreloadedState<S>
      ) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
    }
  
      if (typeof reducer !== 'function') {
      throw new Error('Expected the reducer to be a function.')
    }
    
    let currentReducer = reducer // 当前store中的reducer
    let currentState = preloadedState // 当前store中存储的状态
    let currentListeners = [] // 当前store中放置的监听函数
    let nextListeners = currentListeners // 下一次dispatch时的监听函数
    // 注意:当我们新添加一个监听函数时,只会在下一次dispatch的时候生效。
    
    //...
    
    // 获取state
    function getState() {
        //...
    }
    
    // 添加一个监听函数,每当dispatch被调用的时候都会执行这个监听函数
    function subscribe() {
        //...
    }
    
    // 触发了一个action,因此我们调用reducer,得到的新的state,并且执行所有添加到store中的监听函数。
    function dispatch() {
        //...
    }
   
    //...
    
    //dispatch一个用于初始化的action,相当于调用一次reducer
    //然后将reducer中的子reducer的初始值也获取到
    //详见下面reducer的实现。
    
    
    return {
        dispatch,
        subscribe,
        getState,
        //下面两个是主要面向库开发者的方法,暂时先忽略
        //replaceReducer,
        //observable
    }
}

可以看出,createStore方法创建了一个store,但是并没有直接将这个store的状态state返回,而是返回了一系列方法,外部可以通过这些方法(getState)获取state,或者间接地(通过调用dispatch)改变state

createStore总共接收三个参数:reducer, preloadState, enhancer

  • reducer: 一个纯函数,接收上一个(或初始化)state和action,根据action的type返回新的state
  • preloadState: 一个初始化的state,可以设置store中的默认值
  • enhance: 增强器,用于拓展store的功能,一般是applyMiddleWare(...middleware)

三个关键函数:
1.getState

这个没啥好说的,就是返回currentState

function getState(): S {
    if (isDispatching) {
      //当reducer执行中的时候不能使用getState()
      //state是通过一层一层的reducer传递下来的,每执行一次reducer state就会改变,不能直接从store中读取
      throw new Error(
        'You may not call store.getState() while the reducer is executing. ' +
          'The reducer has already received the state as an argument. ' +
          'Pass it down from the top reducer instead of reading it from the store.'
      )
    }

    return currentState as S
  }

这里需要注意的是,当reducer执行中不能使用getState( ),因为state是通过一层一层的reducer传递下来的,每执行一次reducer, state就会改变,不能直接从store中读取。

2.subscript

//subscribe(listener)函数源码,返回一个取消订阅的函数,
//let unsubscribe = subscribe(listener);     //给listener函数添加了订阅
//unsubcribe()     //给listener函数取消订阅
//实际上就是维护nextListeners数组的过程,订阅就push,取消订阅就splice(index, 1);
function subscribe(listener: () => void) {
  if (typeof listener !== 'function') {
    throw new Error('Expected the listener to be a function.')
  }

  if (isDispatching) {
    throw new Error(
      'You may not call store.subscribe() while the reducer is executing. ' +
      'If you would like to be notified after the store has been updated, subscribe from a ' +
      'component and invoke store.getState() in the callback to access the latest state. ' +
      'See https://redux.js.org/api/store#subscribelistener for more details.'
    )
  }

  let isSubscribed = true     //回调函数被订阅默认的标志

  ensureCanMutateNextListeners()
  nextListeners.push(listener)    //新增订阅在nextListeners中操作

  //返回一个取消订阅的函数
  return function unsubscribe() {
    if (!isSubscribed) {        //如果回调函数已经被取消订阅,则不需要重复取消订阅
      return
    }

    if (isDispatching) {
      throw new Error(
        'You may not unsubscribe from a store listener while the reducer is executing. ' +
        'See https://redux.js.org/api/store#subscribelistener for more details.'
      )
    }

    isSubscribed = false            //取消订阅,这里将回调函数被订阅的标志设置为false

    ensureCanMutateNextListeners()
    const index = nextListeners.indexOf(listener)
    //因为listener已经被取消订阅了,所以在nextListeners将listener删除掉
    nextListeners.splice(index, 1)
    currentListeners = null
  }
}

(1)首先看传入的参数,是一个listener的回调函数当reducer执行完毕之后,会执行这个回调

这个是官网的解释:

listener (_Function_): The callback to be invoked any time an action has been dispatched, and the state tree might have changed. You may call getState() inside this callback to read the current state tree. It is reasonable to expect that the store's reducer is a pure function, so you may compare references to some deep path in the state tree to learn whether its value has changed.

简单解释一下,就是当dispatch(action)完成的时候(应该是reduce执行完成的时候)会去调用listener这个回调函数,状态树可能会改变。可以在listener里面使用getState( )获取到最新的状态。可以通过比较状态树中的一些深层路径的引用去判断状态的值是否发生改变。

(2)如果reducer正在执行,是不能调用subscribe和unsubscribe的

if (isDispatching) {
  throw new Error(
    'You may not call store.subscribe() while the reducer is executing. ' +
    'If you would like to be notified after the store has been updated, subscribe from a ' +
    'component and invoke store.getState() in the callback to access the latest state. ' +
    'See https://redux.js.org/api/store#subscribelistener for more details.'
  )
}

if (isDispatching) {
  throw new Error(
    'You may not unsubscribe from a store listener while the reducer is executing. ' +
    'See https://redux.js.org/api/store#subscribelistener for more details.'
  )
}

我的理解是:因为dispatch函数会在reducer执行完毕后循环执行listeners数组内订阅的更新函数,所以要保证这个时候的listener数组不变,既不能添加更新函数(subscribe)也不能删除更新函数(unsubscribe)。

(3)返回一个取消订阅的函数

//返回一个取消订阅的函数
return function unsubscribe() {
  if (!isSubscribed) {
    return
  }

  //如果正在执行reducer则不能执行unsubscribe函数
  if (isDispatching) {
    throw new Error(
      'You may not unsubscribe from a store listener while the reducer is executing. ' +
      'See https://redux.js.org/api/store#subscribelistener for more details.'
    )
  }

  isSubscribed = false

  ensureCanMutateNextListeners()
  const index = nextListeners.indexOf(listener)
  //因为listener已经被取消订阅了,所以在nextListeners将listener删除掉
  nextListeners.splice(index, 1)
  currentListeners = null
}

(4)我对subscribe函数的理解:实际上就是维护nextListeners数组的过程,订阅就push,取消订阅就splice(index, 1);等到dispatch函数在reducer执行完毕之后会循环执行listeners数组内订阅的更新函数。

相应的代码如下:

function ensureCanMutateNextListeners() {
  if (nextListeners === currentListeners) {
    nextListeners = currentListeners.slice()
  }
}

//新增订阅
ensureCanMutateNextListeners()
nextListeners.push(listener)    //新增订阅在nextListeners中操作

//取消订阅
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
//因为listener已经被取消订阅了,所以在nextListeners将listener删除掉
nextListeners.splice(index, 1)
currentListeners = null

可见,新增订阅和取消订阅都是在nextListener里面操作,不会直接在currentListener里面操作

我们会发现,在每次新增订阅和取消订阅的时候,都会先调用一个ensureCanMutateNextListeners函数。这个函数的语义就是确保可以转变nextListeners。顾名思义,这个函数实质的作用是确保可以改变nextListeners,如果nextListeners与currentListeners一致的话,将currentListeners做一个拷贝赋值给nextListeners,然后所有的操作都会集中在nextListeners。

3.dispatch

function dispatch(action: A) {
  //action不是原生的对象,报错
  if (!isPlainObject(action)) {
    throw new Error(
      'Actions must be plain objects. ' +
      'Use custom middleware for async actions.'
    )
  }

  //对于一个action来说,action中的type是必须的
  if (typeof action.type === 'undefined') {
    throw new Error(
      'Actions may not have an undefined "type" property. ' +
      'Have you misspelled a constant?'
    )
  }

  //reducer正在执行的时候不能调用
  if (isDispatching) {
    throw new Error('Reducers may not dispatch actions.')
  }

  try {
    isDispatching = true
    //currentState与action会流通到所有的reducer
    //所有的reducer的返回值整合后,替换掉当前的currentState
    currentState = currentReducer(currentState, action)     //这句话就是触发相应的reducer
  } finally {
    isDispatching = false
  }

  //最后逐个触发回调函数,回调函数的执行是在dispatch里面
  //执行完reducer之后,需要更新currentListeners,这里也就解释了为什么不能在reducer执行的时候去新增和减少订阅(subscribe, unsubscribe)
  const listeners = (currentListeners = nextListeners)
  for (let i = 0; i < listeners.length; i++) {
    const listener = listeners[i]
    listener()
  }
  
  //为了方便链式调用,dispatch执行完毕后,返回action
  return action
}

(1)传入的参数:一个action

(2)接下来就是一系列的判断检测,有三点要求:

  • action必须得是原生的对象
  • 对于一个action来说,action中的type是必须的
  • reducer正在执行的时候不能调用dispatch

相应的代码如下:

//action不是原生的对象,报错
if (!isPlainObject(action)) {
  throw new Error(
    'Actions must be plain objects. ' +
    'Use custom middleware for async actions.'
  )
}

//对于一个action来说,action中的type是必须的
if (typeof action.type === 'undefined') {
  throw new Error(
    'Actions may not have an undefined "type" property. ' +
    'Have you misspelled a constant?'
  )
}

//reducer正在执行的时候不能调用
if (isDispatching) {
  throw new Error('Reducers may not dispatch actions.')
}

(3)关键部分代码:

try {
  isDispatching = true
  //currentState与action会流通到所有的reducer
  //所有的reducer的返回值整合后,替换掉当前的currentState
  currentState = currentReducer(currentState, action)     //这句话就是触发相应的reducer
} finally {
  isDispatching = false
}

//最后逐个触发回调函数,回调函数的执行是在dispatch里面
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
  const listener = listeners[i]
  listener()
}

//为了方便链式调用,dispatch执行完毕后,返回action
return action

由上面的dispatch函数可见,先执行currentReducer,再分别执行listeners里面的回调

//先执行currentReducer
currentState = currentReducer(currentState, action);
//...

//将nextListener赋值给currentListener,为的是后续的dispatch执行回调函数(listener)过程中,
//可以将这一轮dispatch新增的回调函数(newListener)执行
const listeners = (currentListeners = nextListeners);
//最后逐个触发回调函数,回调函数的执行是在dispatch里面
for (let i = 0; i < listeners.length; i++) {
  const listener = listeners[i]
  listener()
}

(4)总之,dispatch函数就干了两件事,执行了相应的reducer,执行了currentListener注册的回调函数(listener)

3.combineReducers.ts

(1)核心部分源码加解释:

export default function combineReducers(reducers: ReducersMapObject) {
  //获取到所有的reducer的名字,组成数组
  const reducerKeys = Object.keys(reducers)
  //这个finalReducers是最终有效的reducers
  const finalReducers: ReducersMapObject = {}
  for (let i = 0; i < reducerKeys.length; i++) {
    const key = reducerKeys[i]

    if (process.env.NODE_ENV !== 'production') {
      //不是生产环境且存在对应key的reducer
      if (typeof reducers[key] === 'undefined') {
        warning(`No reducer provided for key "${key}"`)
      }
    }

    if (typeof reducers[key] === 'function') {
      finalReducers[key] = reducers[key]
    }
  }
  //做了一系列的判断之后得到了最终的finalReducerKeys数组
  const finalReducerKeys = Object.keys(finalReducers)

  // This is used to make sure we don't warn about the same
  // keys multiple times.
  let unexpectedKeyCache: { [key: string]: true }
  if (process.env.NODE_ENV !== 'production') {
    unexpectedKeyCache = {}
  }

  let shapeAssertionError: Error
  //assertReducerShape用来检查每个reducer有没有默认返回的state
  try {
    assertReducerShape(finalReducers)
  } catch (e) {
    shapeAssertionError = e
  }

  return function combination(
    state: StateFromReducersMapObject<typeof reducers> = {},
    action: AnyAction
  ) {
    if (shapeAssertionError) {
      throw shapeAssertionError
    }

    if (process.env.NODE_ENV !== 'production') {
      const warningMessage = getUnexpectedStateShapeWarningMessage(
        state,
        finalReducers,
        action,
        unexpectedKeyCache
      )
      if (warningMessage) {
        warning(warningMessage)
      }
    }

    let hasChanged = false
    //nextState存放所有的state
    const nextState: StateFromReducersMapObject<typeof reducers> = {}
    for (let i = 0; i < finalReducerKeys.length; i++) {
      //获取每个reducer的名字
      const key = finalReducerKeys[i]
      //获取每个reducer
      const reducer = finalReducers[key]
      //获取每个reducer对应的旧状态
      const previousStateForKey = state[key]
      //调用该reducer,根据这个reducer的旧状态和当前action来生成新的state
      const nextStateForKey = reducer(previousStateForKey, action)    //执行各子reducer以获取子nextState
      if (typeof nextStateForKey === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      //以各自的reducerName为键,新生成的state为值,生成最终的state object。将子nextState挂载到对应的键名,将所有的子state合并到一个对象中
      nextState[key] = nextStateForKey
      //比较经过reducer之后的下一个状态和上一个状态是否相同判断是否hasChanged,只要有一个子state发生改变,整个state就会发生改变
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    hasChanged =
      hasChanged || finalReducerKeys.length !== Object.keys(state).length
      //变化了,返回新的state,否则,返回旧的state
    return hasChanged ? nextState : state     //combineReducers返回的是下一个状态的集合(如果状态改变的话)
  }
}

(1)传入的参数:reducers:是一个由众多的reducer组成的对象

(2)这个函数的大体思路就是:取到所有的reducers的key值 -> 通过筛选得出最终的reducers的key值组成的数组finalReducerKeys和所有reducer组成的数组finalReducers -> 使用finalReducers里面的reducer去操作对应的state -> 比较reducer前后的state是否发生变化 -> 如果state发生了改变,返回一个由reducer名字作为键名,执行 reducer之后的nextStateForKey作为value的对象

4.applyMiddleware.ts

redux原本的dispatch方法只能接受一个对象作为action

用户操作 -> dispatch(action) -> reducer(prevState, action) -> 新的state -> 界面

如果页面要发送请求数据,而且要把数据放在action里面,最终通过reducer的处理,放到store中。这时就需要用到middleware了。

用户操作 -> dispatch(action) -> middleware(action) -> 真正的action -> reducer(prevState, action) -> 新的state -> 界面

这里是在dispatch(action)之后添加了中间件处理,将数据放在action中,返回一个新的action。

applyMiddleware大致会这样使用:

const store = createStore(rootReducer, applyMidddleWare(thunk))

applyMiddleWare(thunk)就相当于一个enhancer,负责拓展redux,说白了就是拓展store的dispatch方法。这个又怎么解释呢?到底是通过什么样的方式去拓展dispatch呢?

下面我使用一个改造版的applyMiddleware方法和redux-thunk的核心代码createThunkMiddleware一起来描述一下是如何实现dispatch的改造的

(1)redux-thunk的核心代码:createThunkMiddleware

//其实这是一个middleware
function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    //next是被thunk改造之前的dispatch,也就是说有可能是最原始的dispatch,也有可能是被其他的中间件改造过的dispatch
    return next(action);
  };
}
//thunk是真正的中间件函数
const thunk = createThunkMiddleware();

//将函数柯里化写成嵌套的形式
function createThunkMiddleware(extraArgument) {
  //真正的中间件函数
  return function({dispatch, getState}) {
    //改造dispatch的函数,这里的next是外部传进来的dispatch,可能是被其他的中间件处理过的,也可能是最原本的
    return function(next) {
      //返回一个新改造的dispatch函数
      return function(action) {
        //如果action是函数,那么执行它,并且将store的dispatch和getState传入,
        //便于我们dispatch的函数内部逻辑执行完之后dispatch真正的action
        if(typeOf action === 'function') {
          return action(dispatch, getState, extraArgument);
        }
        //如果是一个普通的action(也就是对象),直接dispatch
        return next(action);
      }
    }
  }
}

const thunk = createThunkMiddleware();
  • 真正调用的时候,理论上是这样:thunk({ dispatch, getState })(next)(action),其中,thunk({ dispatch, getState})(next)这部分,返回的是一个接受参数为action的改造过后dispatch函数,而这部分会在applyMiddleware中去调用
  • next则是被当前中间件改造之前的dispatch。可以是最原始的dispatch,也有可能是被其他中间件改造过的dispatch。

(2)再看一下简易版的applyMiddleware方法:

function applyMiddleware(store, middlewares) {
  middlewares = middlewares.slice()
  middlewares.reverse()
  let dispatch = store.dispatch
  //感觉这里非常巧妙,相当于是链式调用了middleware函数,返回的dispatch是经过所有的中间件改造过后的dispatch方法
  //类似于这样dispatch = middleware2(store)(middleware1(store)(store.dispatch))
  middlewares.forEach(middleware => (dispatch = middleware(store)(dispatch)))
  //返回一个dispatch更新的store
  return Object.assign({}, store, { dispatch })
}

这与 Redux 中 applyMiddleware() 的实现已经很接近了,但是有三个重要的不同之处

  • 它只暴露一个 store API 的子集给 middleware:dispatch(action)getState()
  • 它用了一个非常巧妙的方式,以确保如果你在 middleware 中调用的是 store.dispatch(action) 而不是 next(action),那么这个操作会再次遍历包含当前 middleware 在内的整个 middleware 链。这对异步的 middleware 非常有用;
  • 为了保证你只能应用 middleware 一次,它作用在 createStore() 上而不是 store 本身。因此它的签名不是 (store, middlewares) => store, 而是 (...middlewares) => (createStore) => (reducers, ...args) => store
  • 看上面一条的解释,就可以解答createStore中的最后一个参数enhancer到底是什么东西了。我们看enhancer的结构,大概是这样:(createStore) => (reducers, ...args) => store.有没有发现enhancer的结构和applyMiddleware(...middlewares)很像呢?没错,applyMiddleware(...middlewares)返回的函数就是enhancer。

(3)最后回归到applyMiddleware的源码

export default function applyMiddleware(
  ...middlewares: Middleware[]
): StoreEnhancer<any> {
  return (createStore: StoreCreator) => <S, A extends AnyAction>(
    reducer: Reducer<S, A>,
    ...args: any[]
  ) => {
    const store = createStore(reducer, ...args)
    let dispatch: Dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    }

    const middlewareAPI: MiddlewareAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args)
    }
    //假设我们只是用了redux-thunk,那么此时的middleware就相当于thunk,就是function({dispatch, getState})
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    //这里的compose的作用就是,将所有的中间件函数串联起来,中间件1结束,作为参数传入中间件2,被它处理,
    //以此类推,最终返回的是被所有的中间件处理完的函数,最开始接受store.dispatch为参数,层层改造后被赋值到新的dispatch变量中
    dispatch = compose<typeof dispatch>(...chain)(store.dispatch)

        //返回的是一个将经过中间件改造的dispatch覆盖原有的dispatch的store对象
    return {
      ...store,
      dispatch
    }
  }
}

这里要注意的点是

  • 假设我们只是用了一个middleware(redux-thunk),就可以暂时抛开compose,那么这里的逻辑就相当于
dispatch = thunk(middlewareAPI)(store.dispatch);

在这里,thunk(middlewareAPI)其实返回的是一个改造dispatch的函数thunk(middlewareAPI)(store.dispatch)返回的就是被改造后的dispatch

  • 加上compose也很好理解,假设有三个middleware,分别命名为middleware1,middleware2, middleware3,其实:dispatch = compose<typeof dispatch>(...chain)(store.dispatch)执行的过程如下:
//先转化为js
dispatch = compose(...chain)(store.dispatch);

//假设middlewares为[middleware1, middleware2, middleware3],则chains为:
//[middleware1(getState, dispatch), middleware2(getState, dispatch), middleware3(getState, dispatch)]
//则上面这句代码其实是这样执行
//chains简化为:[chains1, chains2, chain3]
chain1(chain2(chain3(store.dispatch)))        //返回的是经过chain3, chain2, chain1处理过的dispatch函数

返回的是经过chain3, chain2, chain1处理过的dispatch函数

所以,这里就将store的dispatch方法改造完成了,最后用改造好的dispatch覆盖原来store中的dispatch。

总结一下middleware和applyMiddleware的关系:

  • 中间件(middleware)会帮助我们改造原来store的dispatch方法;
  • applyMiddleware会将多个middleware串联起来,链式调用,返回一个经过众多middleware改造过的最终的dispatch方法。最后将这个改造好的dispatch应用到store上(相当于是将原来的dispatch替换为改造好的dispatch),返回这个更新的store对象

5.bindActionCreators.ts

这个API没啥好讲的,其实也就是做了一件事:就是给每一个ActionCreator加上了dispatch,就是这样:dispatch(ActionCreator(xxx))

核心部分源码:

const boundActionCreators: ActionCreatorsMapObject = {}
  for (const key in actionCreators) {
    const actionCreator = actionCreators[key]
    if (typeof actionCreator === 'function') {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)     //为actioncreator逐个加装上dispatch技能
      //调用:actionCreators.addTodo(content) 相当于 dispatch(addTodo);
    }
  }
return boundActionCreators

使用

bindActionCreator(actionCreators, dispatch)            //actionCreators是一个包含actionCreator的对象,dispatch是指store.dispatch
  • 参数:

    actionCreators (_Function_ or _Object_): 一个 action creator,或者一个 value 是 action creator 的对象。

    dispatch (_Function_): 一个由 Store 实例提供的 dispatch 函数。

  • 返回值:
    (_Function_ or _Object_): 一个与原对象类似的对象,只不过这个对象的 value 都是会直接 dispatch 原 action creator 返回的结果的函数。如果传入一个单独的函数作为 actionCreators,那么返回的结果也是一个单独的函数。

三、redux和flux的区别

redux:

主要解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法:action,store,reducer。工作流程是view调用store的dispatch接收action传入store,reducer进行state操作,view通过store提供的getState获取最新的数据

flux:

flux 也是用来进行数据操作的,有四个组成部分 action,dispatch,view,store,工作流程是 view 发出一个 action,派发器接收 action,让 store 进行数据更新,更新完成以后 store 发出 change,view 接受 change 更新视图。

二者区别:

主要区别在于flux有多个可以改变应用状态的store在Flux中dispatcher被用来传递数据到注册的回调事件但是在redux中只能定义一个可更新状态的store,redux把store和dispatcher合并,结构更加简单清晰。

三、总结

我对redux的理解:redux就是创建一个store来管理所有状态,触发action来改变store


JacksonHuang
74 声望3 粉丝