场景是这样的:
这样一个操作, 需要同时依赖很多个 Model, 因此这些代码不会写在某一个 Model 里边.
有可能是比如 Backbone, 写在 ViewController 里边... 但是这样代码复用不好, 而且 View 会变乱.
我目前采取的方案是用单独一个文件去收集大部分的 Model 操作, 不过问题是, 这个文件会不断变大变乱.
所以这样的问题应该如何解决?
延伸的问题是, 怎样整理这部分代码?
比如我用 React 的 Flux 方案, 尽量将流程理清楚, 就发现这部分代码不知道放在哪里合适..
Flux 将用户操作转化为 Actions, Store 通过 Dispatcher 监听这些 Actions,
一个 Actions 对应多个 Store 的时候... 问题就来了:
我是应该用多个 Actions 分别对应 Store, 还是一个 Action 由多个 Store 来监听?
曾经蜡笔没有小新2017-05-16 17:08:22
用户点击按钮本质上跟用户通过URL访问一样,都是一种『输入』,所以问题和处理机制都是一样的:在view层代码里监听『输入』,处理一些view层(比如按钮组件的toggle、URL的矫正)内部的状态变化,生成/提取出纯粹的、抽象层级更高的(跟view组件或URL细节无关)数据/消息,用某种事件机制广播出去,之后就跟自己没关系了,接下来如果有controller层的话,在这部分的代码里监听这些事件,调用相应model对象的方法(其中可能封装了model对象自己之间的依赖关系和调用,但这里的一对多复杂性不会暴露到外面去),同时也监听某些model对象的状态变化,调用相应view对象的方法(或是重新渲染Virtual DOM)。所有东西绑定完成。
比如我平时用NervJS(model) + DermJS(view)+ URLKit(route) 这样的搭配,NervJS和DermJS对象都有自带的事件方法,此外也可以在view/model对象初始化时传入统一的bus事件对象。
你写一个UI component的时候当然不会希望它依赖特定的model,写一个model组件的时候,也不会希望它依赖特定UI,所以一对多之类的绑定是在另一个地方(专门的业务逻辑代码)完成的,view对象和model对象不需要也不应该知道对方有几个、是哪些,所以也不可能『多个 Actions 分别对应 Store』。
至于『单独一个文件』、『不断变大变乱』的问题,跟配置路由的文件也是一回事,可以参考相关经验。
曾经蜡笔没有小新2017-05-16 17:08:22
flux里,如果需要一个动作对应多个Store,其实也是很好解决的。
在Store里面register回调的时候,可以都对这个动作进行相应就可以了,还可以通过waitFor
来改变相应的顺序。
如果担心代码变乱的话,可以再单独写一个constants
文件,定义好触发的事件名称就可以了。
举个例子:
点击一个按钮,触发send
事件,会更新两个Store
分别是StoreA
和StoreB
。可以写一个constants.js
,先定义事件名称:
constants:
module.exports = {
"ActionTypes": {
"SEND": "SEND"
}
};
然后在两个Store
里面分别注册回调:
StoreA:
var AppDispatcher = require('path/to/disp'),
constants = require('path/to/constants');
StoreA.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (action.type === constants.ActionTypes.SEND) {
// callback A
};
});
StoreB:
var AppDispatcher = require('path/to/disp'),
constants = require('path/to/constants');
StoreB.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (action.type === constants.ActionTypes.SEND) {
// callback B
};
});
在触发点击事件的时候,在Action
中触发Disp
的这个事件,就会顺序执行在StoreA
和StoreB
中注册的回调了:)
曾经蜡笔没有小新2017-05-16 17:08:22
如果你没看过,或者看过但忘了,这是篇值得读的文章:
Patterns For Large-Scale JavaScript Application Architecture
简单而言,你需要有些“约定俗成”的东西,让view和model无需相互依赖(不管是1:1的依赖,还是1:N的依赖)。
用简单的event和observer pattern也可以,如果业务逻辑很复杂,用mediator完成模块间的通信和同步。
PS:理想的情况是,你的每个模块都只知道自己(触发什么事件,聆听什么事件),除此之外都不管,更不会知道对方的instance,或者mediator的instance。