设计实现优雅修改redux数据流的一个库

前言

首先呢~ 在分享前先贴上我写的redux-chef源码,你们若有兴趣能够阅读:redux-chefgit

背景:麻烦的redux社区规范

在使用redux好久之后,有一天写着写着,忽然以为actions/constants/reducers这一套东西显得十分啰嗦(相信不少同窗有这种感受)github

好比看redux的官方实例: todomvc。简简单单一个todomvc,也写出来很多样板代码。redux

哎呀好麻烦吶,我就想简简单单调用改个数据流而已,为啥要我写这么这么长的代码?mvc

因而乎!听闻社区里的那个 dva 很强大,我点开官网看了看它的示例,受其启发,忍不住也花了几个小时写了一个 redux-chef(不过自己和dva没什么关系,类似的地方也就只有model的设计了)来完成我优雅修改redux数据流的设想~app

什么有趣的东西?一个主厨(Chef)!

那么日常的redux,除了上述说的代码样板比较多以外,还有一个点也是修改同一个数据,须要跳跃好几个文件,这也是蛮费心力的,我的感受!框架

通常来讲,一个reducer关注的每每只是其维护的state。那么其实能够把每一个reducer维护的state、以及其全部的action维护在同一个model里面诶dom

根据业务设计本身的model

首先根据业务场景定义本身的model(为了节省空间,代码省略了一部分),而后用redux-chef导出的kitchen煮一下(笑)。这样的models数据就是通过主厨精心加工过的,能够以后在业务代码里优雅调用了~函数

// 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 });
复制代码

备注:完整示例models代码 -> github.com/soulizs/red…优化

而后在将这些加工后的models应用到咱们用redux建立的store里,就能够开始在应用代码里redux-chef设计的调用啦!spa

优雅又简易的调用方式

示例使用redux-chef后的数据流调用方式以下:

// 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>
复制代码

天呐,修改数据流只须要关注models里action函数,而后在应用里直接调用对应的model:models.Cord.setDoubleX();就完成了数据流的改动,而后将对应的state进行connect,即完成了更新后数据的读取。

优雅的是,这种调用给应用开发者带来了流程的简化,只须要关注业务的开发,减小重复的样板代码~

备注:眼尖的同窗或许会发如今 Cord model里面的这两个actionupdatesetDoubleX有点不同。缘由是,setDoubleX因为须要读取model里的state,因此设计成高阶函数,用以自动读取其对应model的state!

固然这种方式也提供了使用咱们自定义使用action的自由,在model.reducer会进行分发。以下示例代码:

// 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>
复制代码

新旧共存,毛问题~

redux-chef的设计哲学

好了使用方式上文都介绍了,其实redux-chef的设计也挺简单的,主要是Chef(), dispatch(), cook(), kitchen(), Chef.apply()这四个API,有兴趣的同窗阅读一下源码便可(也不长)。

简单来讲:

  • 自动聚合全部models的reducer返回给store应用
  • 若是调用了model.action,也就是说是这种操做姿式的话,models.Cord.setDoubleX();,会使用内部自定义的@@${__CHEF_INTERNAL_TYPE__}(${name})分发事件,本质上仍是分发。

  • 上文提到的,若是model.action须要使用自己的state做为依赖计算的话,利用高阶函数自动传入state。

  • 没什么问题是不能用多一层抽象解决的!

小结

  1. 建议你们在看完此文后,拉下此仓库运行一下看看!请点击:redux-chef(注意是improve-reading分支)
  2. 不建议你们在生产环境使用redux-chef。因为社区里存在不少优秀的应用框架,好比 dva 等等。(备注:本人也只是纯粹随便敲敲而已,暂不发布,也不作维护~

谢谢你们的阅读!固然还有不少优化和设计的空间,你们若是有想法与建议,欢迎评论~

(为何起这个名字 redux-chef?由于我常常在半夜敲代码时感到饥饿...)

相关文章
相关标签/搜索