React Flux 为什么要有个 Dispatcher 来间接调用 store 中的方法而不是直接让 view 调用 store 中的方法?

2015-09-28 09:13:48 +08:00
 love
比如

```js
dispatcher.addTodoItem() // 通过回调间接调用 actionStore.addTodoItem()
```

对比

```js
actionStore.addTodoItem()
```
3999 次点击
所在节点    React
19 条回复
iwege
2015-09-28 09:22:04 +08:00
不直接依赖吧?
zrp1994
2015-09-28 09:29:27 +08:00
只是注册了 action 监听, dispather 没有直接调用 store 的方法吧?
love
2015-09-28 09:33:32 +08:00
@zrp1994 @iwege store 注册到 dispatcher , dispatcher 收到消息回调 store 不就是相当于调用 store 的方法吗?有区别吗?
iwege
2015-09-28 09:56:52 +08:00
@love 你自己不是已经说出它的区别了么?就是解耦的用法。多人协助会比较好理解。

如果要理解 flux ,最好和 react 来一起理解。我个人理解 action 实际上就是一个 event 类型的 API ,从 view 层来看,它本来应该是直接和 store 层打交道,但是如果 store 层被替换或者重构的话, API 可能也有相应的变化,比如你觉得 actionStore 的名字不好,或者要重新组织,只要后端在 event 监听里面做修改就好了。

如果采用 flux 的这种做法,大家都依赖 dispatcher ,这样在做单模块的时候无需增加其他模块的具体依赖,可以 store 修改的时候所带来的依赖修改。

不过 flux 这种模式有一个麻烦的地方,就是调用之前先要定义 action ,好处是 action 本身可查,麻烦就是 action 容错性比较低。而且对于 store 与 store 之间没有进行相关的解耦。

而之前在使用 backbone.radio 的时候,先是区分了主动请求 request 和被动回调 event ,对于空请求也不报错,只是警告。同时 request 可以作为同步请求,所以 store 与 store 之间的依赖也可以做解耦。
coffce404
2015-09-28 09:57:32 +08:00
这样所有的修改会先统一经过 Dispatcher ,可以在里面做做中间件什么的
love
2015-09-28 10:26:44 +08:00
@coffce404 不用 dispatcher 也有很多办法中间件啊,用得着用定义 action 这么麻烦的方法吗。

@iwege
import todoActions from './todoActions'
todoActions.addTodoItem()

import todoStore from './todoStore'
todoStore.addTodoItem()
对于使用方来说没什么区别,修改重构时也一样。
coffce404
2015-09-28 10:46:05 +08:00
@love
flux 简单理解是这样: view --> dispatcher --> store --> view
store 可能会有多个,而 dispatcher 则倾向于是单一的。
如果直接调用 store 来执行 action ,那 view 就得知道哪些 store 有这个 action ,如果有 2 , 3 个 store 都注册了这个 action ,那你调用时就得每一个都调用一遍啦,加个 dispatcher 层规避了这个问题
est
2015-09-28 10:50:35 +08:00
还只是个 dispather 嘛。没 dispatcher factory service manager 就不要抱怨了。
love
2015-09-28 11:08:40 +08:00
@coffce404 这样类似事件系统的作法比平时我们写程序的方法方法有什么好处吗?比如
todoStore 的 addTodoItem() {
logStore.logAddTodoItem(...) // 调用不同的 store
this.todos.append(...)
}

我就可以只调用 todoStore 的 addTodoItem 了。
coffce404
2015-09-28 11:49:20 +08:00
@love

解耦
多个 store 不用互相依赖
某个 store 可以随时取消监听,不影响其他 store
新增一个 store 不用修改其他 store 代码

https://www.google.com.hk/?gws_rd=cr,ssl#safe=strict&q=%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F
ChefIsAwesome
2015-09-28 11:50:21 +08:00
多加一层,这样才可以做到 waitfor 。
https://github.com/reflux/refluxjs
这个 flux 实现没有用到 dispatcher
joyee
2015-09-28 11:56:57 +08:00
推荐看看 flux 官网上那个视频,了解一下这个架构的来龙去脉: https://www.youtube.com/watch?list=PLb0IAmt7-GS188xDYE-u1ShQmFFGbrk0v&t=621&v=nYkdrAPrdcw

react 的博客上有解释为什么要搞个 dispatcher 出来,主要就是保证同一时间内只能执行一个 action ,并且在 store 之间有依赖的情况下能够通过这样一个中心避开所谓的 cascading updates (这是 facebook 当年未读消息列表各种 bug 的主要来源,他们改成 flux 架构之后再也没有列表同步的 bug 了……)
http://facebook.github.io/react/blog/2014/07/30/flux-actions-and-the-dispatcher.html#why-we-need-a-dispatcher
joyee
2015-09-28 12:04:15 +08:00
@love 9 楼那种做法就是引发 facebook 的未读消息列表各种 bug 的根源……永远挥之不去的小红点什么的,具体见 flux 官网的那个视频
iwege
2015-09-28 12:16:38 +08:00
@love action 不一定只对应一个 store ,当 action 对应多个 store 的时候这样就简单了。 action 和 store 之间的关系可以是一对多。
Niphor
2015-09-28 12:17:53 +08:00
楼上的头像...我承认我邪恶了...
Niphor
2015-09-28 12:18:17 +08:00
额 楼上上
love
2015-09-28 12:43:28 +08:00
@coffce404 添加 /删除一个 store 有可能还是是依赖别的 store 的代码,因为 store 之间的调用很可能是有顺序的,比如那个例子:
case 'TODO_CREATE':
Dispatcher.waitFor([ PrependedTextStore.dispatchToken, YetAnotherStore.dispatchToken ]);

TodoStore.create(PrependedTextStore.getText() + ' ' + action.text);
break;

@joyee 嗯你这个是一个理由。
joyee
2015-09-28 12:55:19 +08:00
@love https://github.com/facebook/flux/tree/master/examples/flux-chat 建议看看 chat 的 example ,更贴近他们当初发明这个的动机,比 todo 更能体现 flux 的意义
yyfearth
2015-09-28 14:04:39 +08:00
感觉这个比较像 MVVM 里面的 ViewModel
但是并不是完全一样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/224141

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX