介绍
- Redux:状态管理工具,他可以解决组件之间数据共享和数据通信。
特性
- 基于单一store的数据管理(单一来源,集中管理数据更清晰)
- 单向数据流,组件dispatch一个action,执行reducer,reducer里面根据action参数生成一个新的store,然后redux通知组件重新渲染(数据流清晰,对数据约束)
- 数据不可变(它使用纯函数接收先前的 state 和 action,并返回新的 state,性能优化浅比较俩个对象是否改变,也便于调试)
源码实现
createStore的实现
- 作用创建创建store
function (reducer,preloadedState,enhancer){
if ( enhancer可以用 ) {// 中间件增强createStore
return enhancer(createStore)(
reducer,
preloadedState
)
}
let currentReducer = reducer //当前store里面的store
let currentState = preloadedState //当前stroe中的数据
let currentListeners = [] //当前store中放置的监听函数
let nextListeners = currentListeners //下一次dispath的监听函数
// 获取state
function getState(){
return currentState
}
// 添加监听函数,每次dispatch的时候都会调用,返回一个取消监听的函数
function subscribe(listener){
nextListeners.push(listener);
return function unsubscribe() {
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
// 触发一个action,调用reducer得到新的state,执行所有store中的监听函数
function dispatch(action: A) {
currentState = currentReducer(currentState, action)
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
const store = {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
return store
}
复制代码
combineReducers的实现
- 把子reducer合并成一个总的reducer,目的是为了把reducer拆分开来,对每个功能有一个不同的reducer。
function combineReducers(reducers){
// 遍历一遍reducers筛选出有用的reducer
const reducerKeys = Object.keys(reducers)
const finalReducers = {}
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i]
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
const finalReducerKeys = Object.keys(finalReducers)
// assertReducerShape:检测每一个reducer接受一个初始action或一个未知的action时,能够返回效的值
try {
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e
}
return function combination(state,action){
let hasChanged = false // state是否改变标志
const nextState = {} // 新的state
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]// 得到该子reducer的旧的state
const nextStateForKey = reducer(previousStateForKey, action)// 得到该子reducer新的state
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length
return hasChanged ? nextState : state
}
复制代码
Redux 中间件
const store = createStore(reducer,states, applyMiddleware(logger))
// createStore中的当enhancer可以用
if ( enhancer可以用 ) {// 中间件增强createStore
return enhancer(createStore)(
reducer,
preloadedState
)
}
复制代码
- 在createStore中入参enhancer是通过applyMiddlewarec传入中间健返回的
applyMiddleware的实现
function applyMiddleware(...middlewares) {
return (createStore) =>
(
reducer,
preloadedState,
) => {
// 根据传进来的createStore,reducer, preloadedState生成一个store
const store = createStore(reducer, preloadedState)
// 在dispatch改造完成前调用则会抛出错误
let dispatch: Dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
// 将store中的state和dispatch传给中间件
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// compose多个函数组合成一个函数,在compose源码中
// funcs.reduce((a, b) => (...args) => a(b(...args)))
// 返回改造后的dispatch
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
复制代码
- 中间健的基本格式是
({dispatch,state})=>next=>action=>{
//中间件的具体代码
next(action)
}
// 展开箭头函数
// 接受store中的dispath和state
fcuntion (dispatch,state){
// 接受上一个改造后的dispatch,第一个则为store.dispatch
return function (next){
// 改造后的dispatch方法
return function (action){
next(action)
}
}
}
复制代码
redux-logger和redux-thunk
// redux-logger有效代码
const logger = store => next => action => {
console.log('dispatch:',action);
let returnedValue = next(action);
console.log('finish:',action);
return returnedValue
}
// redux-thunk有效代码
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END