V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
love
V2EX  ›  React

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

  •  2
     
  •   love · 2015-09-28 09:13:48 +08:00 · 4168 次点击
    这是一个创建于 3346 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如

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

    对比

    actionStore.addTodoItem()
    
    19 条回复    2015-09-28 14:04:39 +08:00
    iwege
        1
    iwege  
       2015-09-28 09:22:04 +08:00
    不直接依赖吧?
    zrp1994
        2
    zrp1994  
       2015-09-28 09:29:27 +08:00 via iPad
    只是注册了 action 监听, dispather 没有直接调用 store 的方法吧?
    love
        3
    love  
    OP
       2015-09-28 09:33:32 +08:00
    @zrp1994 @iwege store 注册到 dispatcher , dispatcher 收到消息回调 store 不就是相当于调用 store 的方法吗?有区别吗?
    iwege
        4
    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
        5
    coffce404  
       2015-09-28 09:57:32 +08:00
    这样所有的修改会先统一经过 Dispatcher ,可以在里面做做中间件什么的
    love
        6
    love  
    OP
       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
        7
    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
        8
    est  
       2015-09-28 10:50:35 +08:00
    还只是个 dispather 嘛。没 dispatcher factory service manager 就不要抱怨了。
    love
        9
    love  
    OP
       2015-09-28 11:08:40 +08:00
    @coffce404 这样类似事件系统的作法比平时我们写程序的方法方法有什么好处吗?比如
    todoStore 的 addTodoItem() {
    logStore.logAddTodoItem(...) // 调用不同的 store
    this.todos.append(...)
    }

    我就可以只调用 todoStore 的 addTodoItem 了。
    coffce404
        10
    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
        11
    ChefIsAwesome  
       2015-09-28 11:50:21 +08:00
    多加一层,这样才可以做到 waitfor 。
    https://github.com/reflux/refluxjs
    这个 flux 实现没有用到 dispatcher
    joyee
        12
    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
        13
    joyee  
       2015-09-28 12:04:15 +08:00
    @love 9 楼那种做法就是引发 facebook 的未读消息列表各种 bug 的根源……永远挥之不去的小红点什么的,具体见 flux 官网的那个视频
    iwege
        14
    iwege  
       2015-09-28 12:16:38 +08:00
    @love action 不一定只对应一个 store ,当 action 对应多个 store 的时候这样就简单了。 action 和 store 之间的关系可以是一对多。
    Niphor
        15
    Niphor  
       2015-09-28 12:17:53 +08:00
    楼上的头像...我承认我邪恶了...
    Niphor
        16
    Niphor  
       2015-09-28 12:18:17 +08:00
    额 楼上上
    love
        17
    love  
    OP
       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
        18
    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
        19
    yyfearth  
       2015-09-28 14:04:39 +08:00
    感觉这个比较像 MVVM 里面的 ViewModel
    但是并不是完全一样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1079 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 22:45 · PVG 06:45 · LAX 14:45 · JFK 17:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.