<p>dva 改进建议</p>

创建于 2018-08-01  ·  46评论  ·  资料来源: dvajs/dva

dva是对react全家桶的最佳实践整合,已经能够非常有效地提升开发效率了。在实践中,发现dva理论上可以有更好地开发模式。因此,这里我提出一个建议,对dva进行改进,也希望参与到dva的开发之中。

dva的model

dva常规的model编写结构如下所示:

{
  namespace: '', 
  subscriptions:{},  
  state: {},  
  effects: {},  
  reducers: {},  
}

熟悉dva的人大概都知道上面的结构所对应的操作是什么,不展开。这里想谈一谈effects和reducers这两个对象。effects对应的是相关的异步action,reducers对应的是相关的同步action。当我们写一个简单的页面时,effectsreducers中的方法都不会太多。但是当我们写一个复杂页面时,异步的请求与同步的状态更新都会有很多,这样就会导致model中的异步与同步action对象中的方法列表过长,后期维护与代码迭代时,当我们要找到对应的方法时,就不那么地直观和方便。

示例

{
  namespace: '', 
  subscriptions:{},  
  state: {},  
  effects: {
     getUserList(){},
     create(){},
     update(){},
     remove(){},
     removeAll(){}
  },
  reducers: {
     setLoading(){},
     saveModal(){},
     switchView(){},
     createSuccess(){},
     updateSuccess(){},
     removeSuccess(){},
     removeAllSuccess(){}
  }
}

以一个管理用户的页面为例,这里内部实现没有写,非常简单的管理,effectsreducers中已经有五六个函数了。如果这个页面的管理功能更多一些,例如这个列表会继续地增长。当模型变得复杂时,我们阅读代码和寻找一个方法时就需要经常在effectsreducers这两个非常长的函数对象中跳来跳去,写代码异常不便。

我们可以分析一下一个dva单页面的运行情况:

  1. 请求数据未到达浏览器端时,设置loading状态为true,数据到达后设置loading为false。这可以视为一个页面的前置阶段。
  2. 页面中任何的事件操作都需要触发effects中的方法进行异步请求,当请求完成时,调用reducers中的同步方法进行状态更新。从交互上来说,请求失败与请求成功都应该让用户有相对应的感知。

更内聚的设计

程序设计上我们通常讲究『高内聚,低耦合』的设计原则。从dva的model来说,其实是可以实现功能内聚的。也就是说,可以按模块组织相关的功能方法,因此,模块的相关操作从编辑体感上不会四分五裂。

仔细观察,其实effectsreducers分别对应了异步调用与同步调用,写法都是存在自己各自的特征的。effects中都是generator函数或者是async函数,而reducer中是普通的函数。那么,在JS中,我们其实有办法识别这两者的特征的。这是实现功能内聚的前置条件。

我希望的model写法如下:

{
  namespace: 'user',
  state: { },
  userList: {
    before() { },  // 同步,函数显示loading
    after(){}, // 同步,隐藏loading
    *retrieve() {}, // 异步, 请求读取列表
    *create() {}, // 异步,创建用户
    *update(){}, // 异步,更新用户信息
    saveModal(){}, // 同步,显示或者隐藏modal
    successMessage(){}, // 模块内可复用的消息提示
    failMessage() { }, 
  },
}

由于model的默置对象是固定的。因此,只要尊重namespacestatesubscriptionseffectsreducers这些保留关键字,就可以对model进行扩展了。

意思是,不破坏同时兼容原有的model结构。model可以实现一层语法糖的转换功能来实现上面的写法。实质上userList这个模块的方法最终都会转换成经典的model结构,只是从coder的角度来看,更为直观一些,而上线后的结构其实与经典结构无异。

这是一个初步的想法,也请大家斧正和补充。

discussion wontfix

最有用的评论

redux 系列的所有库都强调把同步层和异步层区分开。 美其名曰带来的好处是状态可追溯、便于日志记录、便于数据操作层的业务抽象等等。
但是大多数应用,写代码时 action 的抽象其实就是响应某个操作,或者抽取出某个可复用的动作,是不区分同步异步的。

这也是现在越来越多的 vue 项目直接用 store、 react 用 mobx的原因。
这么多年 redux 风格写下感觉特别啰嗦,跳来跳去。写个异步加载,得写 一个 'sucess' 一个 'error' 一个 'start' 一个 'progress' 。
客观的来讲,这么设计最大的好处是易于测试,不过国内大范围写业务测试的真的少,显得鸡肋~

所有46条评论

我觉得你使用dva-model-extends基本上就可以满足你的需求。

@iceberg211 我觉得不一样,dva-model-extends相当于继承,数据结构和model是一样的。而我这里提出来的,是按模块组织,实际上模块是一层虚拟的组织结构。

redux 系列的所有库都强调把同步层和异步层区分开。 美其名曰带来的好处是状态可追溯、便于日志记录、便于数据操作层的业务抽象等等。
但是大多数应用,写代码时 action 的抽象其实就是响应某个操作,或者抽取出某个可复用的动作,是不区分同步异步的。

这也是现在越来越多的 vue 项目直接用 store、 react 用 mobx的原因。
这么多年 redux 风格写下感觉特别啰嗦,跳来跳去。写个异步加载,得写 一个 'sucess' 一个 'error' 一个 'start' 一个 'progress' 。
客观的来讲,这么设计最大的好处是易于测试,不过国内大范围写业务测试的真的少,显得鸡肋~

用我的这个就可以实现
https://github.com/fangkyi03/dvajs

这也是现在越来越多的 vue 项目直接用 store、 react 用 mobx的原因。

@yeatszhang 这个结论怎么得出的?有数据?

看起来和 rematch 有点像,但 rematch 也是分了 reducer 和 effect 的。

@sorrycc rematch我觉得和dva没太大区别了,除了写法上,让人感觉更自然一点(但实际上dva写久了也觉得很自然)。所以我觉得是model层这一块做多一层语法糖转换(并不改变api),只是在编辑代码时看起来更模块化一些而已。

{
  namespace: 'user',
  state: { },
  userList: {
    before() { },  // 同步,函数显示loading
    after(){}, // 同步,隐藏loading
    *retrieve() {}, // 异步, 请求读取列表
    *create() {}, // 异步,创建用户
    *update(){}, // 异步,更新用户信息
    saveModal(){}, // 同步,显示或者隐藏modal
    successMessage(){}, // 模块内可复用的消息提示
    failMessage() { }, 
  },
}

这里的 userList 有些不清楚,随便取的?另外,作为 redux 的上层封装,我觉得 reducers 应该是要保留的。

我将dva做了一下改良 并且将后台api接口用脚本自动化生成了对应的js
https://github.com/fangkyi03/swaggerToTypeScript
image
然后 你这边如果要做网络请求的话 直接api.sendData就可以了 然后你可以在里面写任意接口的东西
所有的接口都可以进行了补全 以及里面有什么参数都可以直接看到 异常发改变 而且所需要的逻辑 也不需要像dva一样密密麻麻写一堆了 尤其是有多条网络请求的时候

api.sendData(this,[
api.cart(这里是对应的modelName).getList(这里自动生成api的关系 可以直接在ide里面自动回显)(
这里是副作用 每条网络请求都可以做单独的处理 如onCallBack onError timeOut等
)
])

image
api接口文档自动生成的范例

如果同样的东西用dva来写 如有多个网络请求的时候 需要对每个网络请求的接口都做一次处理才可以
举个例子 我删除一个东西的同时进行列表更新
用yield [] 这个方式的确简单 但是接口的是同时调用而不是以一个顺序调用 所以如果网络不稳定的时候 会出现 我删除还没删除完 就调用列表接口 导致数据没有更新的问题

而如果用yield call单个做判断的话 2-3个接口还可以 如果接口很多的话 你要保证数据的准确性 就需要每个接口都判断一下code是否为200 这样真是麻烦的要死

用我这个的话 直接就在api.sendData里面写就可以了 每个接口都是按顺序执行的 而且code这种问题也都不需要你做任何的处理与判断 异常简单 如果你要对请求做数据处理与拦截 直接在对应的接口里面加上
onCallBack或者onError即可

@sorrycc 主观的判断,确实不严密,但是周围抱怨的声音变多,且确实存在迁移的现象。
关于 store 模式和 redux 模式,网上的讨论也很多~ 个人的观点是 redux 有很多酷炫的特性,主要是追求纯函数的思想带来的好处:

  • 可回溯,快照
  • 易于测试
  • Hot reload
  • devtools

如果考虑不支持这几个特性(我们团队来说,开发中真的用到的频率太少了,尤其是最酷炫的devtools),或许可以对外部暴露一个开发效率更高的 api —— 正如封装 dva 追求开发高效封装 redux sugar 一样,必然也损失了部分灵活性,但因为提供了必须的特性且高效,所以有价值。

总结来说,写个很简单的 ajax 请求,逻辑碎片要分散在数个文件且开发过程中需要来回切换,感觉 dva 是可以想办法优化这个现状的。^ ^

个人的意见主要是针对 redux 模式,而不是 dva

我个人觉得把部分逻辑代码分离到model中去实现的确做到了很好的代码分离 并且在effect写所谓的副作用也的确不错 但是当你业务越来越复杂的时候 其实你在model中写的代码 本身就是对于整个系统来说最大的副作用 密密麻麻写一堆 复用的可能性太低 而且场景复杂的时候 在model中还涉及到操作各个state中的数据也变得异常麻烦难以维护 逻辑代码需要写太多了

@fangkyi03 赞同你部分观点 第一部分 是redux 和dva 没有mobx简单,比较啰嗦。
第二部分是支持你说的合并。然而你的方法命名不好 什么userlist难以让人理解 像 reduce effect 则很清楚,而且只是多了一个名字而已,不构成冗余,这点支持sorrycc。
我觉得冗余的地方在于调用dva里的方法的时候 要 加type,和state。这两个属性都是固定的,完全可以用约定大于配置的形式去让用户少打几个字。
至于其他处理异步造成的麻烦,我认为那是saga的锅,异步本来就是then catch这样才是最自然的。saga那种方式本来就只是看起来比较直观 对正确获得结果是有便利的,但是对错误异常处理反而没原来方便。

另外 我想说的是mobx真的很优秀,因为它比redux简洁很多也受到了redux作者的推荐。我认为优点如下

1、它专注于管理状态,把其他工程化的选择权交给用户。 实际上只要实现了状态的订阅模式就已经完成了redux的主要作用,至于怎么处理异步,是否有必要mvc 分层用户自己自由实现。
2、使用了es7的@ ,这个类似于java的注解,可以很便捷的模块化代码。

首先 我的方案是如果你的后台是swagger的话 直接用我写的脚本爬取你们的后台api 然后在你本地直接生成对应的api文档
当你需要调用接口的时候
直接
api.send(this,[
api.cart('cartModel').getCartList()()
])
这里面的所有名字 都是取决于后台接口的取名 这样都不好理解的话 那我想swagger文档也不用看了
因为当你点击swagger文档的时候 在url那边就可以看到对应的接口的名字 你直接对照一下就知道对应接口是哪个了 而且因为直接api自动化生成的文档 如果你想查看详情 直接点一下就可以看到详情
image
这样难道还不能知道这个api是干嘛的吗

其次 我将常用的行为做了更加抽象的分离
你可以重载api这个脚本去挂载你的更多功能
你可以这样如 你要控制对应modal的显示与不显示
api.toggleModalShow(thz,modelName,state){
thz.props.dispatch({type:${modelName}/setValue,payload:{
isShowModal:state
}
}

这样做的好处是 我以后在整个项目里面 任何一个modal我想控制显示的话 不管它在哪个model下面 我都只需要一行代码来进行控制

这里这是一个简单的例子 其他的行为也是一样 比如form表单 当你这个api脚本维护的越来越详细的时候 你的组件内部可以做到只写几行代码就实现这种功能 而且可以无视model的局域性 不用每个model都去写一份代码

很多人喜欢直接封装一个request来做网络请求 这样的请求方式是碎片式的 你无法做统一管理 如我接口报500 或者 报 401等异常的时候 我想捕获这个异常 并且做对应的处理的话 在request里面捕获了异常 但是直接上外层依旧会去直接执行 如果你的网络请求是直接写在页面里面 而不是走sage的话 那就等死吧 我刚才说的那两个需求如果你要实现 就会变得异常艰难 而如果放在saga里面 通过dispatch去控制 你又会遇到状态控制的问题 比如每个接口都要判断一下code是否为200 这种完全是重复工作 其次如果你的网络请求在sage里面抛出了错误 会走到dva的onError里面 但是这里面进来的并不只有网络数据的error 所以导致你程序崩溃抛出异常的时候 你还要判断一下 到底是网络请求出错了 还是普通的变量未定义之类的错误 而且会使你代码不够纯粹 网络错误跟普通错误合在一起用 我个人不推荐

@fangkyi03
1、你后端用什么跟你前端命名不清楚有什么关系,ps 其实你那swagger也就写个文档接口文档有点用
2、关于saga我已经评价过,本来就不好控制异常状态。当然是不走saga,完全可以各种封装一个请求方法。404.还是500还是异常 都可以捕获到模块化处理。代码只写一次。

你有看过我写的那个dvajs吗 可以很方便的解决你所遇到的问题

@fangkyi03 没有,你写的好在哪?

@fangkyi03 虽然在吐槽 dva 的一些地方,不过就现在隔离副作用的框架里面,也就 dva 做的综合最好,以后项目会尝试使用,感谢付出~
建议对初学者最好不要暴露 saga 关于进程控制概念部分(最好saga都可以做到无感知),并不是人人都能理解,更别提用好了~ 可以在文档里面搞个高级功能版面来介绍。
况且用到的场景不多(大多数用也是就是隔离下sideeffect,执行个异步操作)

所以我在说你们关注什么隔离的问题 但是却没有关注 你们写了多少重复代码
我对dva做了处理将一些场景做了优化
分为以下几类 form ModalFrom 等几个
然后你就会发现 你的整个程序 不需要自己创建什么model了 也不需要自己去处理这种代码逻辑了 直接用这几个model来操作就可以了 不管你的表单是归属于哪个model的 都可以直接获取并且处理 然后就可以直接这样了
image
然后你自己写一套这个 把这个变成公用的model 然后所有的东西都直接抽象出来以后 你会发现 我想对表单等场景做修改 直接调用api里面指定命令就可以 我都不需要自己去写逻辑
因为model的关系 每个人对model 对redux的理解程度又不一样 导致每个人的代码风格也是千奇百怪 所以为啥不统一呢

比如我这边表单的创建时这样的
image
这个SearchDropMenu在组件里面会自动在对应的model里面创建对应的表单数据
formData form配置数据
dataSource 表单数据源
typeData 下拉类型数据等
然后通过这样的方式以后 你会发现 我这边所有的东西都可以直接用api的命令来处理了 不管你这个表单如何复杂
而且也无视model的问题 在任何model中我都可以调用固定的命令来实现了
image

如我现在要提交表单 并且要效验这个表单数据的时候 我只需要这样写 所有表单的判断都不需要额外的去写 全部公用一条代码来实现 区别的只是你用这个表单数据以后调用哪个接口提交而已

所以我一直搞不明白 用model 你们写那么多重复的代码 有何意义 你们老说没有隔离 你确定 你们那种隔离的方式对于项目来说 成本真的小吗 像我这样不是更加简单多的呢

我这边这个项目就一个这个model文件因为这个是用来做网络请求的
image

其他的mdoel部分 全部都是直接这样生成的
image
image

根本不需要啊在本地创建那么多无法维护的model文件
而且 如果你要做网络处理 或者异常处理 只需要在这里全局操作就可以 根本无需做其他任何设置
image
比如多条请求中有一条请求失败了 我这边可以直接舍弃后面的请求去执行又或者token失效以后要跳转登录页面 都非常方便

image
比如你要做多条接口请求同时的话 只需要这样做就可以了
这么几条代码已经做到获取网络数据以后 用tranData转换数据格式 并且把转换以后的数据刷新到对应的model了 根本不用像dva那样在effect里面 密密麻麻写一堆的逻辑

@fangkyi03 大概理解了一下你所说的,你的意思是 model里有大量的冗余 很多部分是可以复用的,在你的描述里面,网络请求获取数据后改变相应的数据 和错误处理 这些都是一样的操作。不需要重复的建model。

我开发了一个antd以后 用dva的模式去写 发现 整个团队里面 压根无法统一风格 每个人对model的理解都不同 写出来的代码全是垃圾代码 所以 一个简单的表单为啥要搞这么麻烦呢 为啥不进行一次封装 改成统一的呢
然后你就会发现 什么表单修改 表单操作 都直接调用统一的api不就可以了 整个项目 无比的清爽干净 网络请求也会异常的干净 而不会有一大堆的yield select put这种 我个人认为 正常开发 不应该去接触这些东西 因为用了这些以后 会导致你的代码质量根本无法控制 你无法规定说网络请求别人应该这么获取数据 这么刷新数据等等 所以代码质量直线下降 有些时候看团队里面别人写的代码 你自己都要想半天 为啥数据刷新是这样的 又为啥要做其他操作

@fangkyi03 所以 你的槽点是 dva的model 是一个一个的,而你的models是一群model可以集中处理。好处是多个model存在相同的类似操作时 可以复用一套reduce或effect。

model的存在 应该只限于store数据的隔离 而不应该去隔离函数的调用 这样会引发很大的代码质量问题

或者换句话说 model的存在只应该用于store 而不应该让普通开发接触到这个层面 应该写成通用的api 因为你让普通开发接触到model的话 根本压根无法限制代码质量 每个人的想法都不一样 写法也不一样 你这么多可以改变redux流程的函数 如yield select take call等 你能去约束别人应该先调用哪个 后调用哪个吗 不可能的

@fangkyi03 我感觉你说的这个问题是存在的,那就是dva当前对相同effect或者reduce不太方便集中化处理。从而每个地方都要粘贴一遍。
但是我觉得这个问题你觉得突出是因为你们最大化走dva了(在官网的例子里(dashboard)就是这样。还有一些umi的官网例子也是这样 往这个方向(最大化使用dva)引导了),如果最小化走dva只在需要跨组件更新的时候才使用dva 那么基本很少会有集中化处理复用的。
比如,您这个 请求数据进行,我写的话 我就不走dva,统一走自己封装的request,这样性能还好,也集中化处理了。
如果,实在是需要多个model复用 reduce和effect,
咱也可以用 从配置namespace的数组中,map出来一堆model对象,都加上相同的reduce或effect,最后用app model方法加进来。这样也省了代码,添加这一块和umi的约定不一样。

以上。还是最小化使用dva比较好。你的槽点是因为你最大化使用dva带来的,不是dva的固有缺陷,我认为无足轻重。

一样东西推出来以后 但是你会发现 所有人都不是dva作者 一堆小白看着各种人写的文章然后就投入了生产 然后就会发现 这些人写出的n个项目都是垃圾项目 也就意味着 很多实用dva来做项目的 反而不能保证代码质量了 这不是跟dva的初衷背道而驰了吗

统一处理的好处是显而易见的 在提高代码质量 让整个项目变得更加可维护的同时还能给你带来所有dva可以带给你的所有性能以及特性 何乐而不为呢 就像dva说的 只提供了8个api yield select call 等等 但是这个离实际的成品还有很长一段路要走呢 这中间会产生很多的可能 所以你还在造路写框架 我这边已经开上小车了 这就是差距啊 而且 你能保证你这个项目写的代码 在下一个项目能直接进行使用吗 不能把 一直重复 重复 又重复的 去写逻辑处理 简直让我不能忍

@fangkyi03 我感觉dva的初衷就是简化redux 。
redux两大功能 1、是跨组件通信。2、按照它的框架写把数据流搞成了mvc,我觉得你们想最大化使用dva的原因也是想当成一种规范搞mvc。也就是您说的mvc后可以统一复用处理数据层的逻辑,可以多个页面绑定一个数据处理中心(model)。
但是我还是认为最小化处理比较好,只有1、你a页面的数据,在bc页面操作可能会改变a页面的数据 这种多页面关联数据源的。2、相同的更新数据view逻辑。这些情况下,才适合放到dva里。
如果你要集中处理,同样可以自己写一个数据处理函数 比如写在你通用的util里,像刚刚的请求就是。
如果你全部都写在dva里, 涉及到跨组件数据变化的和没涉及到的都写到一起了,从统一这个点这是个优点,但是也带来了两个缺点
1、model变得很多,不清爽了。下次你要组织通用model的时候要分辨的更多了。
2、store变大了,带来了多余的计算。

……………………………………
最后,再回到 统一处理model上,像你写的,也是从modellist中取出来,再map加上共有的reduce或effect方法,这种操作,是在dva原有功能上的操作(是做加法),dva并没有阻碍你这么做,不需要改变什么。而且你的这种操作,也不好封装成一个方法变成通用的增强方法,还是得自己亲自精细化的去写,因此,你需要dva 怎么变动呢?

所以我说 你还是没有理解我的核心思想 我的意思是把model只用来当做一个store来使用 现在不是也流行类似无状态组件嘛 放弃state使用props也是有好处的 虽然因为redux的一些槽点会导致一些多余的运算 但是这个计算量还是可以预估的 毕竟你的model只是用来放数据的 不会有其他多余的逻辑处理 其实这个计算量 主要还是体现在redux的这个槽点 当你发起一个dispatch的时候 所有的reduce 所有的监听 所有的中间件都会参与运算 所以我针对这个写了一个fastDva 只保留实际项目中需要的部分 其他的都被舍弃了 带来了更大的提升 而且可以更加适合我现在的这个概念
https://github.com/fangkyi03/fastdva-core

所以我会在以后把dva全部转成我写的那个fastDva

@fangkyi03 我觉得我理解你所说的,model只当做一个store,像reduce、effect是对数据进行处理的,不用放在model里。对吧。你这样做的目的是考虑到很多model的数据处理操作都是一样的,因此你可以把他们一群一起处理 像你上面搞的modellist。
我的问题是:dva原有的功能并没有阻碍你把一群model批量加reduce,effect。也没有阻碍你只把model当做一个store啊。 你这么操作是在dva上做加法,并没有改变什么啊。

原有的那个方式 你如何去管理一个团队里面的整体风格呢 我这样做 在优化的同时 性能 代码质量 都能提高 而且还能复用写的代码逻辑 几乎写一次就不需要再次写了 哪怕换一个项目都可以 既然如此 何乐而不为呢

@fangkyi03 同样有困惑的点,包括 vuex 的作者和 redux 的作者,都说提供了最大限度的自由,怎么组织项目以及怎么组织状态的存放都由使用者自己决定(redux作者稍微倾向将所有页面状态都放在 model 中统一管理)。 但是多人一起做工程化项目的时候,是需要一个最佳实践指南的,不是每一个人都愿意并且有能力去思考代码怎么组织最好,并且正好大家思考的结果还一致~~

这点 angular 的工程化思想就做的好多了,模子有了照着写即可。 铁打的营盘,流水的兵~

换句话说,工程化的问题也不是必须要 dva 解决,但如果 dva 不解决这个问题,最好也能有上层的工具封装,或者提供指南和更多的约束来应对这样的开发需求~ 拓宽生态

我觉得 还是优先解决刚需比较好点 扩展性太高 但是实际开发 并不需要这么多东西 因为一个未知的定义 导致性能下降感觉也是很浪费的

需要用到dva的场景:
1、不同页面间 特别是跨组件 存在关联数据源的或者可以订阅同一数据源的。
2、不同的组件或页面 有 相同的数据跟新view的逻辑的。
在【2】中 ,为什么我说是不同组件和页面,因为react是组件化的,一部分可复用的viewmodel功能直接封进组件了。 @yeatszhang ng用mvvm或者说mvc收益比react更多是因为 ng没有把数据封进一个组件。ng是以数据为单元的,react是以组件为单元的。以数据为单元的好处是解耦页面,数据处理可复用的地方更多,代价是有些页面需要耦合数据的也一股脑的解耦了,还得写代码把他们捏在一起。
因此 【2】的使用场景也大大降低了。

以下是我认为完全没必要的。
i、如果是相同的数据处理逻辑但是不需要更新显示的,则不需要走dva 也可以复用。
2、相同的处理数据处理逻辑也需要更新显示的 但是放到model里去connect和直接setstate几乎代码量一样的。
以上一个典型的场景就是 发送请求获取数据。请求下来跟新数据,从state中获取和从store中获取几乎是一样的代码量。如果没有几个页面间关联同一个数据源,根本没必要走dva。

…………………………………………
再扯关于统一管理的问题,我们讨论使用这些工具的优劣,就像我们讨论 使用筷子 勺子 叉子 都可以完成吃饭这一需求,它们各有利弊,为了统一要求全部用筷子或者勺子吃 都可以。所以尽量使用dva和尽少量使用dva都可以作为参考规范。

我觉得 还是按照你实际项目的行为做抽象划分更加合适点 比如你的modalForm form等一些行为以及组件 你把常用的行为都写好了 下次直接用就行了 这套代码 放哪个项目都可以愉快的使用 这种体验才是最好的 以后遇到这种表单的 都不需要重复写逻辑了 拿来就用 而且还方便写成api文档 也方便团队内部新人培训以及统一风格维护 也可以将这部分写的独立出来成一个单独的api接口 然后快速迭代 之后开发任何antd或者涉及到表单的页面直接张手即来 都不用想任何复杂逻辑去考虑数据传递的问题

会写样式的很多 但是实际会写框架的人很少 dva给了你一把刀 但是却没有告诉你如何才是正确的雕朵花方式
导致市面上 烂菜根的项目越来越多 然后就把问题归根于redux跟dva太难用 或者不好用 虽然有部分原因 但是我觉得 还是因为没有一个统一的解决方案的关系 导致百花齐鸣 而且很多的创业型或者外包型公司 根本没办法从底层去优化这种东西 只能跟着潮流 现在流行用什么 不管三七二十一 直接拿来就用 然后就跟滚雪球一样 垃圾的项目是越来越多 这也是我们中国这边外包跟创业型公司的一个通病吧

Redux新轮子。。。Rectx

请教一个问题,rematch的effects可以有返回值,dva的effects可以有吗?

请教一个问题,复赛的效果可以有返回值,DVA的影响可以有吗?

effect可以返回数据 是以promise的方式

@fangkyi03 明白了,谢谢。

我想要的只是一个嵌套的命名空间。
例子:

const model = {
  namespace: 'foo',
  model: {
    namespace: 'bar',
    state: {
      msg: "Hello, World!"
    }
  }
}

通过foo.bar.msg获得msg foo.bar.msg

以上只是粗略的例子...

此问题已自动标记为陈旧,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。

@sorrycc 建议将type的格式从namespace/action更改为action@namespace这种,这种更具有语义.

此页面是否有帮助?
0 / 5 - 0 等级