We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
作者: HerryLo
本文永久有效链接: https://didiheng.com/front......
Redux是JavaScript状态容器,提供可预测化的状态管理。
在实际开发中,常搭配React + React-redux使用。这代表了目前前端开发的一个基本理念,数据和视图的分离。
redux应运而生,当然还有其他的一些状态管理库,如Flux、Elm等,当然,我们这里只对redux进行解析。
创建redux的store对象,需要调用combineReducers和createStore函数,下面解释不包含中间件。
const reducer = combineReducers({ home: homeNumber, number: addNumber }) const store = createStore(reducer) // 暂时挂载在window下,下面会使用到 window.$reduxStore = store
首先调用combineReducers函数,将多个reducer函数作为参数传入,源码如下:
// reducers即是传入的参数对象 function combineReducers(reducers) { // ......省略 return function combination(state = {}, action) { let hasChanged = false const nextState = {} for (let i = 0; i < finalReducerKeys.length; i++) { // finalReducerKeys 是传入reducers对象的key值 const key = finalReducerKeys[i] // finalReducers 等价于 reducers const reducer = finalReducers[key] const previousStateForKey = state[key] // 运行reducer函数,返回一个state // 核心:调用combination函数,实际就是循环调用传入的reducer函数 const nextStateForKey = reducer(previousStateForKey, action) nextState[key] = nextStateForKey // hasChanged = hasChanged || nextStateForKey !== previousStateForKey } // hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length // 返回state对象 return nextState } } // 源码地址:https://github.com/reduxjs/redux/blob/master/src/combineReducers.ts#L139
上面的代码其实非常简单,combineReducers函数运行,返回一个新的combination函数。combination函数的主要作用是返回一个挂载全部state的对象。 当combination函数被调用时,实际就是循环调用传入的reducer函数,返回state对象。将combination函数作为参数传入到createStore函数中。
function createStore(reducer, preloadedState, enhancer) { // reducer --> combination函数 let currentReducer = reducer // 全部的state属性,挂载在currentState上 let currentState = preloadedState // 下面的中间件会用到 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { // 第二个参数是一个函数,没有第三个参数的情况 enhancer = preloadedState // 将preloadedState重置 preloadedState = undefined } if (typeof enhancer !== 'undefined') { // 存在中间件时,将createStore传入中间件函数,调用enhancer函数,return结束。 return enhancer(createStore)(reducer, preloadedState) } function dispatch(action) { // currentReducer --> combination函数 currentState = currentReducer(currentState, action) } // 初始化调用dispatch,创建初始state dispatch({ type: ActionTypes.INIT }) const store = ({ dispatch: dispatch, subscribe,s getState, replaceReducer, [$$observable]: observable } return store } // 源码地址:https://github.com/reduxjs/redux/blob/master/src/createStore.ts#L60
reducer就是传入的combination函数,preloadedState是初始化的state(没有太大的作用),enhancer是中间件,没有第三个参数enhancer的情况下,同时第二个参数preloadedState是一个函数,preloadedState被赋值给enhancer。
reducer
调用dispatch函数初始化,currentReducer即是传入combination函数,就向上文提到的,调用combination函数实际就是循环调用reducer函数。所有的state对象,被挂载在内部变量currentState上。存在中间件enhancer时,将createStore传入中间件函数,调用enhancer函数,return结束,这个下文会继续讲到。
dispatch
currentReducer
combination
currentState
创建的store对象,暴露出的方法如下:
const store = ({ // 分发 action,这是触发 state 变化的惟一途径。 dispatch: dispatch as Dispatch<A>, // 变化监听器 subscribe, // 获取store下的 全部state getState, // 替换 store 当前用来计算 state 的 reducer replaceReducer } return store
dispatch函数触发action,调用reducer函数,修改state。subscribe函数可以监听变化state的变化。getState函数获取全部state。replaceReducer函数替换用来计算state的reducer函数。
subscribe
getState
replaceReducer
通过combineReducers函数合并reducer函数,返回一个新的函数combination(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore函数,函数内部通过dispatch,初始化运行传入的combination,state生成,返回store对象
combineReducers
createStore
最好把上面看懂之后,再看中间件部分!!下面对中间件进行分析:
redux-thunk只是redux中间件的一种,也是比较常见的中间件。redux-thunk库允许你编写与store交互的异步逻辑。
redux-thunk
import thunkMiddleware from 'redux-thunk' const reducer = combineReducers({ home: homeNumber, number: addNumber }) const store = createStore( reducer, applyMiddleware( thunkMiddleware, // 异步支持 ) )
createStore函数支持三个参数,如果第二个参数preloadedState是一个函数,而没有第三个参数enhancer的话,preloadedState会被赋值给enhancer。
下面会以redux-thunk中间件作为例子,下面就是thunkMiddleware函数的代码:
// 部分转为ES5代码,运行middleware函数会返回一个新的函数,如下: return ({ dispatch, getState }) => { // next实际就是传入的dispatch return function (next) { return function (action) { // redux-thunk核心 if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }; } // 源码地址:https://github.com/reduxjs/redux-thunk/blob/master/src/index.js
redux-thunk库内部源码非常的简单,github: redux-thunk 源码,允许action是一个函数,同时支持参数传递,否则调用方法不变。
// 中间件调用 return enhancer(createStore)(reducer, preloadedState) 等价于 return applyMiddleware( thunkMiddleware, )(createStore)(reducer, preloadedState)
redux的中间件,从applyMiddleware函数开始,它主要的目的就是为了处理store的dispatch函数。
dispatch函数
// 支持多个中间件传入 export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, ...args) => { // 创建 store const store = createStore(reducer, ...args) const middlewareAPI = { getState: store.getState, dispatch: (action, ...args) => dispatch(action, ...args) } // 遍历运行中间件函数,将middlewareAPI作为参数传入 // middleware对应上面的redux-thunk库核心代码,当然也支持多个中间件 const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 核心:将所有中间件传入到compose中,返回一个新的dispatch dispatch = compose(...chain)(store.dispatch) // 照常返回一个store对象,dispatch已经被处理过了 return { ...store, dispatch } } } // 源码地址:https://github.com/reduxjs/redux/blob/master/src/applyMiddleware.ts#L55
applyMiddleware函数接收多个middlewares参数,返回一个store对象。通过createStore创建store对象,middlewareAPI对象挂载getState和dispatch,循环middlewares中间件,将middlewareAPI作为参数传入每个中间件。遍历结束以后,拿到了一个包含所有中间件新返回函数的一个数组,将其赋值给变量chain。
applyMiddleware
// 遍历之后chain的值,这里只是拿redux-thunk库作为例子 // next 就是 dispatch chain = [function (next) { return function (action) { if (typeof action === 'function') { // redux-thunk核心 return action(dispatch, getState, extraArgument); } return next(action); }; }, ...更多中间件]
// 数组chain 保存所有中间件新返回函数 dispatch = compose(...chain)(store.dispatch)
compose的主要作用就是运行所有中间件函数后,返回一个经过处理的dispatch函数。
// compose函数 return chain.reduce((a, b) =>{ return (...args)=> { return a(b(...args)) } }
chain是保存中间件函数的数组,具体的内部结构参见上面👆,下面来分析一下compose函数的调用逻辑。
// chain 类比为 [fn1, fn2, fn3, fn4] [fn1, fn2, fn3, fn4].reduce((a, b) =>{ return (...args)=> { return a(b(...args)) } }
调用过程如下:
经过 compose 处理过之后, 最后的返回值就是 (...args) => fn1(fn2(fn3(fn4(...args)))),这个的arg就是 store.dispatch函数。最后将返回函数赋值给dispatch,就是我们需要的dispatch函数了。而如果只有一个中间件的话,就会直接返回了。
(...args) => fn1(fn2(fn3(fn4(...args))))
applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数
这里的使用是不配合react-redux+react的;
window.$reduxStore = store store.dispatch(action); let { aState } = store.getState()
上面是直接将其挂载在window对象之下,这样可以配合任何前端框架使用,当然这样肯定是不优雅的,后面我再会专门讲一篇配合react-redux使用的;
在这里调用store.dispatch函数,实际就是再次调用循环遍历调用reducer函数,更新之后被保存在createStore函数的内部变量currentState上。通过store.getState函数,返回currentState变量,即可得到所有state。
内容有点多,需要总结一下
1.redux创建Store:通过combineReducers函数合并reducer函数,返回一个新的函数combination(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore函数,函数内部通过dispatch,初始化运行传入的combination,state生成,返回store对象。
2.redux中间件:applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数
3.redux使用:实际就是再次调用循环遍历调用reducer函数,更新state
解析到这里就结束了,redux真的非常函数化,满满的函数式编程的思想,非常的模块化,具有很强的通用性,觉得非常赞👍👍
ps: 微信公众号:Yopai,有兴趣的可以关注,每周不定期更新,分享可以增加世界的快乐
The text was updated successfully, but these errors were encountered:
HerryLo
No branches or pull requests
redux解析
作者: HerryLo
本文永久有效链接: https://didiheng.com/front......
Redux是JavaScript状态容器,提供可预测化的状态管理。
在实际开发中,常搭配React + React-redux使用。这代表了目前前端开发的一个基本理念,数据和视图的分离。
redux应运而生,当然还有其他的一些状态管理库,如Flux、Elm等,当然,我们这里只对redux进行解析。
redux创建Store
创建redux的store对象,需要调用combineReducers和createStore函数,下面解释不包含中间件。
combineReducers函数
首先调用combineReducers函数,将多个reducer函数作为参数传入,源码如下:
上面的代码其实非常简单,combineReducers函数运行,返回一个新的combination函数。combination函数的主要作用是返回一个挂载全部state的对象。 当combination函数被调用时,实际就是循环调用传入的reducer函数,返回state对象。将combination函数作为参数传入到createStore函数中。
createStore函数
reducer
就是传入的combination函数,preloadedState是初始化的state(没有太大的作用),enhancer是中间件,没有第三个参数enhancer的情况下,同时第二个参数preloadedState是一个函数,preloadedState被赋值给enhancer。调用
dispatch
函数初始化,currentReducer
即是传入combination
函数,就向上文提到的,调用combination
函数实际就是循环调用reducer函数。所有的state对象,被挂载在内部变量currentState
上。存在中间件enhancer时,将createStore传入中间件函数,调用enhancer函数,return结束,这个下文会继续讲到。创建的store对象,暴露出的方法如下:
dispatch
函数触发action,调用reducer函数,修改state。subscribe
函数可以监听变化state的变化。getState
函数获取全部state。replaceReducer
函数替换用来计算state的reducer
函数。通过
combineReducers
函数合并reducer函数,返回一个新的函数combination
(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore
函数,函数内部通过dispatch,初始化运行传入的combination
,state生成,返回store对象redux中间件
最好把上面看懂之后,再看中间件部分!!下面对中间件进行分析:
redux-thunk
只是redux中间件的一种,也是比较常见的中间件。redux-thunk
库允许你编写与store交互的异步逻辑。createStore函数支持三个参数,如果第二个参数preloadedState是一个函数,而没有第三个参数enhancer的话,preloadedState会被赋值给enhancer。
下面会以
redux-thunk
中间件作为例子,下面就是thunkMiddleware函数的代码:redux-thunk
库内部源码非常的简单,github: redux-thunk 源码,允许action是一个函数,同时支持参数传递,否则调用方法不变。applyMiddleware函数
redux的中间件,从applyMiddleware函数开始,它主要的目的就是为了处理store的
dispatch函数
。applyMiddleware
函数接收多个middlewares参数,返回一个store对象。通过createStore创建store对象,middlewareAPI对象挂载getState和dispatch,循环middlewares中间件,将middlewareAPI作为参数传入每个中间件。遍历结束以后,拿到了一个包含所有中间件新返回函数的一个数组,将其赋值给变量chain。compose函数
compose的主要作用就是运行所有中间件函数后,返回一个经过处理的dispatch函数。
chain是保存中间件函数的数组,具体的内部结构参见上面👆,下面来分析一下compose函数的调用逻辑。
调用过程如下:
经过 compose 处理过之后, 最后的返回值就是
(...args) => fn1(fn2(fn3(fn4(...args))))
,这个的arg就是 store.dispatch函数。最后将返回函数赋值给dispatch,就是我们需要的dispatch函数了。而如果只有一个中间件的话,就会直接返回了。applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数
redux使用
这里的使用是不配合react-redux+react的;
上面是直接将其挂载在window对象之下,这样可以配合任何前端框架使用,当然这样肯定是不优雅的,后面我再会专门讲一篇配合react-redux使用的;
在这里调用store.dispatch函数,实际就是再次调用循环遍历调用reducer函数,更新之后被保存在createStore函数的内部变量currentState上。通过store.getState函数,返回currentState变量,即可得到所有state。
结束:
内容有点多,需要总结一下
1.redux创建Store:通过
combineReducers
函数合并reducer函数,返回一个新的函数combination
(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore
函数,函数内部通过dispatch,初始化运行传入的combination
,state生成,返回store对象。2.redux中间件:applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数
3.redux使用:实际就是再次调用循环遍历调用reducer函数,更新state
解析到这里就结束了,redux真的非常函数化,满满的函数式编程的思想,非常的模块化,具有很强的通用性,觉得非常赞👍👍
ps: 微信公众号:Yopai,有兴趣的可以关注,每周不定期更新,分享可以增加世界的快乐
The text was updated successfully, but these errors were encountered: