Open xiaochengzi6 opened 2 years ago
Redux 不能自动处理 store.dispatch 的返回的函数(异步函数),但在 dispatch和 reducer 之间增加一个中间件就可以将这个函数转换成适合redux处理的内容。 action ---> dispatch ---> middleware 1 ---> middleware 2 ---> reducers
Redux 不能自动处理 store.dispatch 的返回的函数(异步函数),但在 dispatch和 reducer 之间增加一个中间件就可以将这个函数转换成适合redux处理的内容。
action ---> dispatch ---> middleware 1 ---> middleware 2 ---> reducers
中间件就是一个函数对 store.dispatch() 方法的重新包装,也就是在 action 和 reducer 这两步之间添加了其他功能生成一种洋葱模型
store.dispatch()
action
reducer
store.dispatch会被层层包装成一个洋葱模型,这样就可以在里面执行一些副作用和异步操作。
//reducer const Redux = (state, action) => state //store const store = createStore(Redux) //action { type: 'NAME', value: 'value' } //store.dispatch store.dispatch({ type: 'NAME', value: 'value' })
由于:
Reducer是纯函数只承担对 State 的计算。 view 和state 一一对应也不能作为承担其他的功能。 action 存放数据的对象,只能被别人操作,自己不能执行任何操作。
Reducer是纯函数只承担对 State 的计算。
view 和state 一一对应也不能作为承担其他的功能。
action 存放数据的对象,只能被别人操作,自己不能执行任何操作。
所以: 就选定在store.dispatc() 方法中添加功能既可以在数据 action 发出时做出相应的动作也可以更容易的操作 action 。
那就先做一个简易的中间件看看
let next = store.dispatch; store.dispatch = function dispatch_Log(action) { console.log('action:', action); next(action); console.log('next state:', store.getState()) }
可以看到将原来的方法进行保留然后重新对 dispatch 重新定义在调用 next(action) 时候开始打印功能。让我们在回顾一下对中间件的定义:中间件就是一个函数对 store.dispatch() 方法的重新包装,也就是在 action 和 reducer 这两步之间添加了其他功能生成一种洋葱模型
import { createStore, applyMiddleware } from 'redux'; //state const state = { score: 2 } //Reducer const reducer = (state, action) => { switch(action.type) { case: 'SCORE_VALUE' return { ...state, score: action.score} } } //中间件 (看不懂没关系往下看) cosnt logger = ({ getState, dispatch } => next => action =>{ console.log('log开始:',action) let returnValue = next(action) console.log('log结束:', action) return returnValue }) //store let store = createStore(reducer, state, applyMiddleware(logger)) //store.dispatch store.dispatch({ type: 'SCORE_VALUE', score: 5 })
首先先看 createStore 这个函数接收三个参数 createStore(reducer, [preloadedState], enhancer)
createStore
createStore(reducer, [preloadedState], enhancer)
reducer (Function): 接收两个参数,分别是当前的 state 树和要处理的 [action](https://www.redux.org.cn/docs/Glossary.html#action),返回新的 [state 树](https://www.redux.org.cn/docs/Glossary.html#state)。 [preloadedState] (any): 初始时的 state。 enhancer (Function): enhancer 是一个组合 store creator 的高阶函数,返回一个新的强化过的 store creator。(请牢牢记住这一点)
preloadedState
enhancer
为了深入了解 enhancer 来先看以下 它接收那些参数 。由于 enhancer 是返回一个新的强化后的 store creator 可以先看到 StoreCreator 它的函数签名:
StoreCreator 的函数签名为
StoreCreator
type StoreCreator = (reducer: Reducer, State: ?State) => Store
enhancer 的签名为
type enhancer = (next: StoreCreator) => StoreCreator
现在就明白了 enhancer 作为一个类似于 react 高阶组件的去接收 StoreCreator 然后在返回一个加强版的 StoreCreator 需要注意:enhancer 就是指代的 applyMiddleware(...midleware)
applyMiddleware(...midleware)
//Reducer const reducer = (state, action) => { switch(action.type) { case: 'SCORE_VALUE' return { ...state, score: action.score} } } //store let store = createStore(reducer, applyMiddleware(thunk))
注明:高阶组件是 react 的一种设计模式 它是一个函数接收一个组件为参数然会在返回新的组件
export default function applyMiddleware(...middlewares) { // 接收 createStore 参数 return (createStore) => (reducer, preloadedState, enhancer) => { // 保存 store disptch chain var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch var chain = [] // 传递给中间件的参数 var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } // 注册中间件调用链,并由此可知,所有的中间件最外层函数接收的参数都是{getState,dispatch} // 这里就可以明确为什么编写中间件(logger)需要接收一个{ getState, dispatch } chain = middlewares.map(middleware => middleware(middlewareAPI)) //compose 函数起到代码组合的作用:compose(f, g, h)(...args) 效果等同于 f(g(h(...args))) //从此也可见:所有的中间件最二层函数接收的参数为 dispatch,一般我们在定义中间件时这个形参不叫dispatch 而叫 next, //是由于此时的 dispatch 不一定是原始 store.dispatch,有可能是被包装过的新的 dispatch。 dispatch = compose(...chain)(store.dispatch) //被包装后的dispatch 也被称为 next // 返回经 middlewares 增强后的 createStore return { ...store, dispatch } } }
//中间件 (现在看懂了吗?) cosnt logger = ({ getState, dispatch } => next => action =>{ console.log('log开始:',action) let returnValue = next(action) console.log('log结束:', action) return returnValue })
这里就能感受到 action --中间件--> reducer 中间件的拦截作用
action --中间件--> reducer
异步中间件 redux-thunk 简化版
const thunk = ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState); //如果传入的 action 是个函数那么他会将参数传入里面 //直到 action 不是参数的情况下开始执行 next(action) //这里没有完全明白 看看阮一峰博客 } return next(action); }; function thunk () { return function ({dispatch, getState}) { return function (next) { return function (action) { if(typeof action === 'function'){ return action(dispatch, getState) } return next(action) } } } }
// ...funcs === [f,g,h], store.dispatch export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg //透传 } if (funcs.length === 1) { return funcs[0] } const last = funcs[funcs.length - 1] const rest = funcs.slice(0, -1) return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)) // composed 是上次计算的返回值 f 是当前元素 last(...args)是初值第一运行就会赋值给 composed // f(g(h(store.dispatch))) }
array.reduceRight(function(total, currentValue, currentIndex, arr), initialValue) 作用:从数组的末尾向前将数组中的数组项执行 所定义的函数 操作
array.reduceRight(function(total, currentValue, currentIndex, arr), initialValue)
[解读 Redux 中间件的原理][https://juejin.cn/post/6844903502641102855]
一、中间件(midleware)是做什么的?
中间件就是一个函数对
store.dispatch()
方法的重新包装,也就是在action
和reducer
这两步之间添加了其他功能生成一种洋葱模型store.dispatch会被层层包装成一个洋葱模型,这样就可以在里面执行一些副作用和异步操作。
二、为什么中间件去改造 dispatch 而不是在其他的位置?
1) 先来看一下Redux的一个同步的例子。
由于:
所以: 就选定在store.dispatc() 方法中添加功能既可以在数据 action 发出时做出相应的动作也可以更容易的操作 action 。
那就先做一个简易的中间件看看
可以看到将原来的方法进行保留然后重新对 dispatch 重新定义在调用 next(action) 时候开始打印功能。让我们在回顾一下对中间件的定义:中间件就是一个函数对
store.dispatch()
方法的重新包装,也就是在action
和reducer
这两步之间添加了其他功能生成一种洋葱模型三、使用示例
首先先看
createStore
这个函数接收三个参数createStore(reducer, [preloadedState], enhancer)
为了深入了解 enhancer 来先看以下 它接收那些参数 。由于 enhancer 是返回一个新的强化后的 store creator 可以先看到 StoreCreator 它的函数签名:
StoreCreator
的函数签名为enhancer
的签名为现在就明白了
enhancer
作为一个类似于 react 高阶组件的去接收StoreCreator
然后在返回一个加强版的StoreCreator
需要注意:enhancer
就是指代的applyMiddleware(...midleware)
为了直观的感受 enhancer 的魅力 所以...
这里就能感受到
action --中间件--> reducer
中间件的拦截作用异步中间件 redux-thunk 简化版
compose 函数实现
array.reduceRight(function(total, currentValue, currentIndex, arr), initialValue)
作用:从数组的末尾向前将数组中的数组项执行 所定义的函数 操作[解读 Redux 中间件的原理][https://juejin.cn/post/6844903502641102855]