Redux相关术语的个人理解

        关于redux的术语讲解在redux的文档有相当详细的讲解,这里会讲一些个人结合源码的理解,希望能帮助到大家学习。

状态与state

        在个人看来,状态于代码而言就是一堆带有语义的数据。

        状态管理即是数据管理,state就是一个具有明确语义的数据集中地,它的语义就是描述了一个事物的状态。

store

        store是一个对象,负责了状态整个变化过程中一系列事件的调度,并暴露相对应的接口给予用户使用。

        具体体现就是createStore的返回值。

return {
    // 发布一个action
    dispatch,
    // 注册listener用来订阅sotre的更新
    subscribe,
    // 获取state的接口
    getState,
    // 替换reducer函数
    replaceReducer,
    // 可观察对象。Observable 类型表示用于处理异步数据流的基本协议之一。
    [$$observable]: observable,
  }

reducer

        reducer必须是一个函数,源码里会存在reducer的参数校验。

if (typeof reducer !== 'function') {
    throw new Error(
      `Expected the root reducer to be a function. Instead, received: '${kindOf(
        reducer
      )}'`
    )
  }

        reducer用于返回一个新的state。源码里在dispatch的末尾会直接调用reducer并把返回值给到state。

try {
  isDispatching = true
  currentState = currentReducer(currentState, action)
} finally {
  isDispatching = false
}

action

        action仅仅是一个带有type属性的普通对象。dispatch函数对action进行检查后就会把它给到reducer。

if (!isPlainObject(action)) {
      throw new Error(
        `Actions must be plain objects. Instead, the actual type was: '${kindOf(
          action
        )}'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples.`
      )
    }

    if (typeof action.type === 'undefined') {
      throw new Error(
        'Actions may not have an undefined "type" property. You may have misspelled an action type string constant.'
      )
    }

使用node的EventEmiter简单还原Redux的流程

        redux的核心就在createStore上,通过createStore和reducer可以拿到一个store,通过这个store去管理数据。

        示例采用官方的“计数器”。

import { createStore } from 'redux'

function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

let store = createStore(counterReducer)

store.subscribe(() => console.log(store.getState()))

store.dispatch({ type: 'counter/incremented' })
store.dispatch({ type: 'counter/incremented' })
store.dispatch({ type: 'counter/decremented' })
  • 这段代码声明了一个用于更新计数器状态的reducer
  • 然后通过createStore和reducer创建了一个store
  • 打印计数器状态的函数订阅了store的更新
  • 最后store连续发布了三个action进行了更新

        基于这个业务实现的丐版createStore如下

import EventEmiter from 'events'

export function createStore(reducer) {
  let state
  const emitter = new EventEmiter()

  emitter.subscribe = function(listener) {
    emitter.on('dispatch', listener)
  }

  emitter.dispatch = function(action) {
    state = reducer(state, action)
    emitter.emit('dispatch')
  }

  emitter.getState = function(){
    return state
  }
  return emitter
}

createStore函数做了以下事情

  • 利用了闭包保存state,
  • 生成了一个事件发射器。
  • 订阅函数负责将listener注册在emitter的dispatch事件上。
  • 发布函数负责传递action和执行reducer,然后更新state和触发dispatch事件。
  • getState则负责获取state这个内部变量的值。

参考资料