摘要:概述前一章讲了的,这一章讲中很神奇的中间件。我们也可以使用中间件来扩展的功能。当然一样的,这样的中间件也已经存在了,日志的中间件也已经存在了查看效果资源源码
0x000 概述
前一章讲了redux的Action Creator,这一章讲redux中很神奇的中间件。
0x001 手写中间件在项目中,我们经常会有记录一些事件或者在某些事件发生的时候做某些事的需求,比如api接口鉴权操作、日志记录操作等,一般我们都可以用中间件来完成,中间件具有可拔插、可扩展的特点。我们也可以使用中间件来扩展redux的功能。
记录每一次的action和state变化
我们在之前是这么使用redux的:
import {createStore} from "redux" function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 default: return state } } let store = createStore(counter) store.subscribe(() => { // console.log(store.getState()) }) const ACTION_INCREMENT = "INCREMENT" const increment = () => { return { type: ACTION_INCREMENT } } const action = increment() store.dispatch(action) store.dispatch(action) store.dispatch(action)
通过store.dispatch完成对数据的修改,现在我们希望记录每一次对数据的修改,我们可以这么做
console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState())
效果很明显,猪才会这么做
封装1:封装成函数,可以,经常我们也是这么做的,但是不好
const dispatch = (store, action) => { console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) } dispatch(store, action)
封装2:hack掉store.dispatch,没毛病,但是不够优雅并且如果希望有多个中间件不太好办,并且希望中间键可以串联起来
const storeDispatch=store.dispatch store.dispatch= (action) => { console.log("action", action.type) storeDispatch(action) console.log("next state", store.getState()) } store.dispatch(action)
封装3:多个中间件串联
这里写了两个中间键,一个是前中间件,一个是后中间件,在执行 before(store)的时候,其实我们已经将store.dispatch替换成了before的dispatch,所以我们在after对dispatch第二次替换的时候,const storeDispatch = store.dispatch中的 store.dispatch其实是before.dispatch,所以,当我们执行store.dispatch(increment())的时候,调用链其实是:store#dispatch=after#dispatch -> before#dispatch -> before#console.log -> store#dispatch -> after#console.log
const before = (store) => { const storeDispatch = store.dispatch const dispatch=(action) => { console.log("before", action.type,store.getState()) storeDispatch(action) } store.dispatch = dispatch } const after = (store) => { const storeDispatch = store.dispatch const dispatch = (action) => { storeDispatch(action) console.log("after",action.type,store.getState()) } store.dispatch=dispatch } before(store) after(store) store.dispatch(increment())
查看输出:
封装4:隐藏hack,减少样板代码
const before = (store) => { const storeDispatch = store.dispatch return (action) => { console.log("before", action.type, store.getState()) storeDispatch(action) } } const after = (store) => { const storeDispatch = store.dispatch return (action) => { storeDispatch(action) console.log("after", action.type, store.getState()) } } const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() middlewares.forEach(middleware => { store.dispatch = middleware(store) }) } applyMiddleware(store, before, after) store.dispatch(increment())
封装5:不使用 hack
const before = (store) => { return (storeDispatch) => { return (action) => { console.log("before", action.type, store.getState()) storeDispatch(action) } } } const after = (store) => { return (storeDispatch) => { return (action) => { storeDispatch(action) console.log("after", action.type, store.getState()) } } } const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() let storeDispatch = store.dispatch middlewares.forEach(middleware => { storeDispatch = middleware(store)(storeDispatch) }) // store.dispatch = storeDispatch return {...store, ...{dispatch: storeDispatch}} } store = applyMiddleware(store, before, after) store.dispatch(increment())
封装6:优化中间件写法
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result }
最终的完整代码
import {createStore} from "redux" // reducer function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 default: return state } } // 创建 store let store = createStore(counter) // action const ACTION_INCREMENT = "INCREMENT" // action creator const increment = () => { return { type: ACTION_INCREMENT } } // 前中间件 const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } // 后中间件 const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } // 应用中间件 const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() let storeDispatch = store.dispatch middlewares.forEach(middleware => { storeDispatch = middleware(store)(storeDispatch) }) // store.dispatch = storeDispatch return {...store, ...{dispatch: storeDispatch}} } // 返回了新的 store store = applyMiddleware(store, before, after) // 发出 action store.dispatch(increment())0x002 redux applyMiddleware
前面写了一个applyMiddleware方法,虽然可以用,但是官方其实也提供了这个方法,并且比我们写的更好一点
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } let store = createStore(counter, applyMiddleware(before, after)) store.dispatch(increment())
可以看出来,相较于我们自己写的`applyMiddleware`,官方提供的可以直接传递给`createStore`,而无需在次对`store`进行操作。0x003 异步action
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } const asyncAction=()=>{ return (dispatch)=>{ setInterval(()=>{ dispatch(increment()) },1000) } } const asyncMiddleware = store => storeDispatch => action => { if (typeof action === "function") { return action(storeDispatch) } else { return storeDispatch(action) } } let store = createStore(counter, applyMiddleware(asyncMiddleware,before,after)) store.dispatch(asyncAction())
这里写了一个asyncMiddleware,他判断传入的action是否是一个函数,如果是一个函数,那就直接执行这个函数,同时将dispatch作为参数,则在asyncAction我们就能直接访问到dispatch了,就可以在asyncAction适当的时候再次dispatch了。
当然一样的,这样的中间件也已经存在了:redux-thunk,日志的中间件也已经存在了:redux-logger
import thunkMiddleware from "redux-thunk" import { createLogger } from "redux-logger" const store = createStore( counter, applyMiddleware( thunkMiddleware, createLogger() ) ) store.dispatch(increment())
查看效果
0x004 资源源码
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/97936.html
摘要:的全称是统一资源定位符英文,可以这么说,是一种标准,而网址则是符合标准的一种实现而已。渲染器,将组件渲染到页面上。 0x000 概述 从这一章开始就进入路由章节了,并不直接从如何使用react-route来讲,而是从路由的概念和实现来讲,达到知道路由的本质,而不是只知道如何使用react-route库的目的,毕竟react-route只是一个库,是路由的一个实现而已,而不是路由本身。 ...
摘要:入门实例前端技术真是日新月异,搞完不搭配个数据流都不好意思了。关于的用法,这只是基础入门的部分,还有的多的搞基操作,比如异步数据流和配合。 redux —— 入门实例 TodoListshowImg(https://segmentfault.com/img/bVtSeH); Tip 前端技术真是日新月异,搞完 React 不搭配个数据流都不好意思了。满怀期待的心去翻了翻 flux,简直...
摘要:异步实现设计需要增加三种通知异步请求发起的异步请求成功的异步请求失败的示例代码如下返回参数完全可以自定义。这种分别在请求开始前,请求成功后,请求失败后发送。表示数据的有效性,他的作用是在异步请求发送失败后,告诉当前的数据是过时的数据。 说明:对Redux不了解的同学可先看看这篇文章Redux技术架构简介(一) 前言 这里说的Redux异步实现,是专指Redux中的异步Action实现,...
摘要:接下来的函数就有点难度了,让我们一行一行来看。上面实际的含义就是将数组每一个执行的返回值保存的数组中。需要注意的是,方法返回值并不是数组,而是形如初始值的经过叠加处理后的操作。从而实现异步的。 这段时间都在学习Redux,感觉对我来说初学难度很大,中文官方文档读了好多遍才大概有点入门的感觉,小小地总结一下,首先可以看一下Redux的基本流程:showImg(https://segm...
阅读 2597·2021-09-26 10:17
阅读 3225·2021-09-22 15:16
阅读 2135·2021-09-03 10:43
阅读 3265·2019-08-30 11:23
阅读 3661·2019-08-29 13:23
阅读 1308·2019-08-29 11:31
阅读 3691·2019-08-26 13:52
阅读 1399·2019-08-26 12:22