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这个内部变量的值。