介绍
- Redux:状态管理工具,他可以解决组件之间数据共享和数据通信。
特性
- 基于单一store的数据管理(单一来源,集中管理数据更清晰)
- 单向数据流,组件dispatch一个action,执行reducer,reducer里面根据action参数生成一个新的store,然后redux通知组件重新渲染(数据流清晰,对数据约束)
- 数据不可变(它使用纯函数接收先前的 state 和 action,并返回新的 state,性能优化浅比较俩个对象是否改变,也便于调试)
源码实现
createStore的实现
function (reducer,preloadedState,enhancer){
if ( enhancer可以用 ) {
return enhancer(createStore)(
reducer,
preloadedState
)
}
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
let nextListeners = currentListeners
function getState(){
return currentState
}
function subscribe(listener){
nextListeners.push(listener);
return function unsubscribe() {
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
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){
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)
try {
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e
}
return function combination(state,action){
let hasChanged = false
const nextState = {}
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
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))
if ( enhancer可以用 ) {
return enhancer(createStore)(
reducer,
preloadedState
)
}
- 在createStore中入参enhancer是通过applyMiddlewarec传入中间健返回的
applyMiddleware的实现
function applyMiddleware(...middlewares) {
return (createStore) =>
(
reducer,
preloadedState,
) => {
const store = createStore(reducer, preloadedState)
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)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
({dispatch,state})=>next=>action=>{
next(action)
}
fcuntion (dispatch,state){
return function (next){
return function (action){
next(action)
}
}
}
redux-logger和redux-thunk
const logger = store => next => action => {
console.log('dispatch:',action);
let returnedValue = next(action);
console.log('finish:',action);
return returnedValue
}
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}