- 11.3 完成redux主流程的源码阅读
- 11.4 完成redux中间件相关源码
- 11.5 了解一下ES,CQRS,Flux相关知识
前言:
- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是学习源码整体架构系列的第8期,链接:学习 redux 源码整体架构,深入理解 redux 及其中间件原理 - 掘金 (juejin.cn)。
准备:
源码:
git clone https://github.com/lxchuan12/redux-analysis.git
cd redux-analysi/redux
npm i
npm run build
好吧,实不相瞒,这样我报错了,具体为啥,尚未查明,毕竟我一直都有很多奇奇怪怪的问题😒,so,‘机智’的summer,直接看若川大佬的examples文件夹里面的内容,也不会影响使用。
redux
好久没看redux了,先浅浅的复习一下吧
redux是什么?
Redux是 JavaScript 应用的状态容器,提供可预测的状态管理。
视图与状态一一对应,所有的状态保存在一个对象里面
- 首先用户通过
View发出Action- 但是,你view发出一次消息就需要一个
Action,我们会定义一个函数来生成Action,这个函数就叫做Action Creators
- 但是,你view发出一次消息就需要一个
- 发出
Action就要使用dispatch,大概就是告诉store告诉你想干嘛 - 然后
Store调用ReducerReducer是一个函数,他接受两个参数PreStateAction
- 他会返回一个新的
State给Store - 至于为啥会有很多
reducer,因为他们将reducer进行拆分了拆分 Reducer 逻辑 | Redux 中文官网
Store会将这个新的State给viewState一旦发生变化,那么我们store就会监听subscribe,然后更新view
这里放一张官网的图,我感觉其实还是很清晰的。
redux的特点
- 单向数据流
- 将
UI和数据逻辑分开
步入正题:
index.js
index.js是入口文件,其实就是提供了reudx的方法
export {
createStore,
combineReducers,
bindActionCreators,
applyMiddleware,
compose,
__DO_NOT_USE__ActionTypes
}
createStore.js
主要就是用于
Store的生成
store身上有几个函数
dispatch:将subscribe收集到的函数依次执行subscribe:订阅收集函数,将他们存放在数组中,等到触发dispatch依次执行,返回一个unsubscribe函数,取消订阅,取消监听replaceReducer: 主要用于redux开发者工具,对比当前和上一次操作的异同getState:就是获取当前的state
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
首先先来看最简单的两个
getState()
获取当前的
state
function getState() {
if (isDispatching) {
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
}
replaceReducer()
替换当前
reducer,并重新初始化state
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.REPLACE })
}
subscribe()
注册监听事件,然后返回取消的函数,将所有的订阅函数都用一个数组来存放
function subscribe(listener) {
let isSubscribed = true
ensureCanMutateNextListeners()
//将当前的这个事件放进监听数组
nextListeners.push(listener)
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-reference/store#subscribelistener for more details.'
)
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
这里面我们维护了一个nextListeners,它里面存放的就是监听的函数
这个函数监听忘了,那么就将他从数组里面删除
dispatch()
分发action的唯一方式
function dispatch(action) {
//删去一些判断语句,这里只看逻辑部分
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
- 虽然
dispatch传递的参数是action - 但是内部其实调用的是
Reducer,传递参数currentState和action - 按顺序执行
listener,其实里面就是一个个的事件嘛? - 返回
action
每次CreateStore()的时候,就会dispatch一个init Action,是为了生成初始化的State树
总结:
第一次阅读redux,并对redux的工作流程有了一定的认识
之前也会使用redux,其实真的只会CV,这次不至于像之前那么困惑了
知道其实reudx内部由五个部分组成,其中createStore是主流程
CreateStore里面由于四个函数组成
这样一层层的看,其实还是很明了的