创建一个 React Store来存储应用中所有的 State,应用中应仅有一个 Store

DEMO

先从一个 Demo 来开始源码分析:

  1. import { createStore } from 'redux'
  2. function todos(state = [], action) {
  3. switch (action.type) {
  4. case 'ADD_TODO':
  5. return state.concat([action.text])
  6. default:
  7. return state
  8. }
  9. }
  10. let store = createStore(todos, ['Use Redux'])
  11. store.dispatch({
  12. type: 'ADD_TODO',
  13. text: 'Read the docs'
  14. })
  15. console.log(store.getState())

上面的代码,我们就能得到state['Use Redux', 'Read the docs']

createStore 源码

方法:createStore(reducer, [preloadedState], [enhancer])
参数:

  1. reducer 是一个函数,该函数接收两个参数: stateaction,且返回一个新的state
  2. preloadedState 初始时的state
  3. enhancer 是一个组合式的store creator的高阶函数,返回一个新的强化过的store creator。于middleware有些相似。

返回值: 一个新的state对象。

  1. export default function createStore(reducer, preloadedState, enhancer) {
  2. // 有初始化函数state,且没有传第三参数,enhancer 即为 preloadedState
  3. if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
  4. enhancer = preloadedState
  5. preloadedState = undefined
  6. }
  7. if (typeof enhancer !== 'undefined') {
  8. if (typeof enhancer !== 'function') {
  9. // 不是空,且不是一个函数,报错
  10. throw new Error('Expected the enhancer to be a function.')
  11. }
  12. // 对enhancer进行createStore处理,把reduce传进去
  13. return enhancer(createStore)(reducer, preloadedState)
  14. }
  15. // reducer必需是一个函数
  16. if (typeof reducer !== 'function') {
  17. throw new Error('Expected the reducer to be a function.')
  18. }
  19. let currentReducer = reducer
  20. let currentState = preloadedState
  21. let currentListeners = []
  22. let nextListeners = currentListeners
  23. let isDispatching = false
  24. function ensureCanMutateNextListeners() {
  25. // 当这里指向同一个数组时,创建一个新的副本
  26. if (nextListeners === currentListeners) {
  27. nextListeners = currentListeners.slice()
  28. }
  29. }
  30. // 返回当前的state
  31. function getState() {
  32. return currentState
  33. }
  34. // redux的订阅函数,订阅 dispatch
  35. function subscribe(listener) {
  36. if (typeof listener !== 'function') {
  37. throw new Error('Expected the listener to be a function.')
  38. }
  39. if (isDispatching) {
  40. throw new Error('')
  41. }
  42. let isSubscribed = true
  43. ensureCanMutateNextListeners() // 每次调用,确保nextListeners变量是新的副本
  44. nextListeners.push(listener) // 存储订阅者
  45. // 返回一个可以取消订阅的函数
  46. return function unsubscribe() {
  47. if (!isSubscribed) {
  48. return
  49. }
  50. if (isDispatching) {
  51. throw new Error('')
  52. }
  53. isSubscribed = false
  54. ensureCanMutateNextListeners()
  55. const index = nextListeners.indexOf(listener)
  56. nextListeners.splice(index, 1)
  57. currentListeners = null
  58. }
  59. }
  60. // 派发函数,用于触发 reducer 修改 state
  61. function dispatch(action) {
  62. if (!isPlainObject(action)) { // action 必需是对象
  63. throw new Error(
  64. 'Actions must be plain objects. ' +
  65. 'Use custom middleware for async actions.'
  66. )
  67. }
  68. if (typeof action.type === 'undefined') { // 必需有type字段
  69. throw new Error(
  70. 'Actions may not have an undefined "type" property. ' +
  71. 'Have you misspelled a constant?'
  72. )
  73. }
  74. // 派发中不能再调用,想了一下,正常情况下不会走到这里,哪怕是多次调用也不会
  75. // 可能存在的就是是 reducer 里面又调用了dispatch,这样会导致state不是最新的。
  76. if (isDispatching) {
  77. throw new Error('Reducers may not dispatch actions.')
  78. }
  79. try {
  80. // 正在派发中。。。
  81. isDispatching = true
  82. currentState = currentReducer(currentState, action)
  83. } finally {
  84. isDispatching = false
  85. }
  86. // 派发结束,执行所有订阅者函数
  87. const listeners = (currentListeners = nextListeners)
  88. for (let i = 0; i < listeners.length; i++) {
  89. const listener = listeners[i]
  90. listener()
  91. }
  92. return action
  93. }
  94. // 如果你的应用实现了代码拆分,需要动态加载reducer,需要用到
  95. function replaceReducer(nextReducer) {
  96. if (typeof nextReducer !== 'function') {
  97. throw new Error('Expected the nextReducer to be a function.')
  98. }
  99. currentReducer = nextReducer
  100. dispatch({ type: ActionTypes.REPLACE })
  101. }
  102. // 该方法的作用是,订阅store的变化,适用于所有observable的类库。比如 RxJS。
  103. function observable() {
  104. const outerSubscribe = subscribe
  105. return {
  106. subscribe(observer) {
  107. if (typeof observer !== 'object' || observer === null) {
  108. throw new TypeError('Expected the observer to be an object.')
  109. }
  110. // // 用于给 subscribe 注册的函数,严格按照 Observable 的规范实现,observer 必须有一个 next 属性。
  111. function observeState() {
  112. if (observer.next) {
  113. observer.next(getState())
  114. }
  115. }
  116. observeState()
  117. const unsubscribe = outerSubscribe(observeState)
  118. return { unsubscribe }
  119. },
  120. // $$observable 即为 Symbol.observable,也属于 Observable 的规范,返回自身。
  121. [$$observable]() {
  122. return this
  123. }
  124. }
  125. }
  126. // 初始化时执行一个 INIT 类型的action
  127. dispatch({ type: ActionTypes.INIT })
  128. return {
  129. dispatch,
  130. subscribe,
  131. getState,
  132. replaceReducer,
  133. [$$observable]: observable
  134. }
  135. }

总结

createStore方法返回一个对象,里面包含了一些常用的 API

  1. dispatch 派发任务
  2. subscribe 实现了观察者模式,每次dispatch后都会遍历一遍currentListeners
  3. getState 返回当前的 state
  4. replaceReducer 代码拆分时动态加载reducer