设计实现优雅修改redux数据流的一个库 - redux-chef
前言
首先呢~ 在分享前先貼上我寫的redux-chef源碼,大家如有興趣可以閱讀:redux-chef
背景:麻煩的redux社區(qū)規(guī)范
在使用redux很久以后,有一天寫著寫著,突然覺得actions/constants/reducers這一套東西顯得十分啰嗦(相信很多同學(xué)有這種感覺)
比如看redux的官方實例: todomvc。簡簡單單一個todomvc,也寫出來不少樣板代碼。
哎呀好麻煩吶,我就想簡簡單單調(diào)用改個數(shù)據(jù)流而已,為啥要我寫這么這么長的代碼?
于是乎!聽聞社區(qū)里的那個 dva 很強大,我點開官網(wǎng)看了看它的示例,受其啟發(fā),忍不住也花了幾個小時寫了一個 redux-chef(不過本身和dva沒什么關(guān)系,相似的地方也就只有model的設(shè)計了)來完成我優(yōu)雅修改redux數(shù)據(jù)流的設(shè)想~
什么有趣的東西?一個主廚(Chef)!
那么平常的redux,除了上述說的代碼樣板比較多之外,還有一個點也是修改同一個數(shù)據(jù),需要跳躍好幾個文件,這也是蠻費心力的,個人感覺!
一般來說,一個reducer關(guān)注的往往只是其維護的state。那么其實可以把每個reducer維護的state、以及其所有的action維護在同一個model里面誒
根據(jù)業(yè)務(wù)設(shè)計自己的model
首先根據(jù)業(yè)務(wù)場景定義自己的model(為了節(jié)省空間,代碼省略了一部分),然后用redux-chef導(dǎo)出的kitchen煮一下(笑)。這樣的models數(shù)據(jù)就是經(jīng)過主廚精心加工過的,可以之后在業(yè)務(wù)代碼里優(yōu)雅調(diào)用了~
// models/index.ts import { kitchen } from '../redux-chef'; const Cord = {namespace: 'cord',state: { x: 3, y: 4 },action: {update(x: number, y: number) {return { x, y };},setDoubleX: () => (state: any) => {return {...state,x: state.x * 2}}},reducer: function (state: any, action: any) {//...} };const Points = {namespace: 'points',state: [],reducer: function (state: any, action: any) {//...} }; export default kitchen({ Cord, Points }); 復(fù)制代碼備注:完整示例models代碼 -> github.com/soulizs/red…
然后在將這些加工后的models應(yīng)用到我們用redux創(chuàng)建的store里,就可以開始在應(yīng)用代碼里redux-chef設(shè)計的調(diào)用啦!
優(yōu)雅又簡易的調(diào)用方式
示例使用redux-chef后的數(shù)據(jù)流調(diào)用方式如下:
// App.ts import models from './models/index.ts';function updateCord() {models.Cord.update(generateRandNum(), generateRandNum()) }function setDoubleCordX() {models.Cord.setDoubleX(); } // render <Button onClick={updateCord}>update cord x & y</Button> <Button onClick={setDoubleCordX}>double cord x</Button> 復(fù)制代碼天吶,修改數(shù)據(jù)流只需要關(guān)注models里action函數(shù),然后在應(yīng)用里直接調(diào)用對應(yīng)的model:models.Cord.setDoubleX();就完成了數(shù)據(jù)流的改動,然后將對應(yīng)的state進行connect,即完成了更新后數(shù)據(jù)的讀取。
優(yōu)雅的是,這種調(diào)用給應(yīng)用開發(fā)者帶來了流程的簡化,只需要關(guān)注業(yè)務(wù)的開發(fā),減少重復(fù)的樣板代碼~
備注:眼尖的同學(xué)或許會發(fā)現(xiàn)在 Cord model里面的這兩個actionupdate,setDoubleX有點不一樣。原因是,setDoubleX由于需要讀取model里的state,所以設(shè)計成高階函數(shù),用以自動讀取其對應(yīng)model的state!
當(dāng)然這種方式也提供了使用我們自定義使用action的自由,在model.reducer會進行分發(fā)。如下示例代碼:
// actions/index.ts import { dispatch } from '../redux-chef'; export function setCordX(x: number) {dispatch({type: constants.SET_CORD_X, x}); }// App.ts import { setCordX } from './actions/index.ts'; // render <Button onClick={() => setCordX(generateRandNum())}>set cord x</Button> 復(fù)制代碼新舊共存,毛問題~
redux-chef的設(shè)計哲學(xué)
好了使用方式上文都介紹了,其實redux-chef的設(shè)計也挺簡單的,主要是Chef(), dispatch(), cook(), kitchen(), Chef.apply()這四個API,有興趣的同學(xué)閱讀一下源碼即可(也不長)。
簡單來說:
- 自動聚合所有models的reducer返回給store應(yīng)用
- 如果調(diào)用了model.action,也就是說是這種操作姿勢的話,models.Cord.setDoubleX();,會使用內(nèi)部自定義的@@${__CHEF_INTERNAL_TYPE__}(${name})分發(fā)事件,本質(zhì)上還是分發(fā)。
-
上文提到的,如果model.action需要使用本身的state作為依賴計算的話,利用高階函數(shù)自動傳入state。
-
沒什么問題是不能用多一層抽象解決的!
小結(jié)
謝謝大家的閱讀!當(dāng)然還有很多優(yōu)化和設(shè)計的空間,大家如果有想法與建議,歡迎評論~
(為什么起這個名字 redux-chef?因為我經(jīng)常在半夜敲代碼時感到饑餓...)
轉(zhuǎn)載于:https://juejin.im/post/5cd155e2e51d456e7079f2df
總結(jié)
以上是生活随笔為你收集整理的设计实现优雅修改redux数据流的一个库 - redux-chef的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过git将本地代码上传码云
- 下一篇: 渲染管线简介