Heim > Fragen und Antworten > Hauptteil
Die Szene sieht so aus:
Ein solcher Vorgang muss auf vielen Modellen gleichzeitig basieren, sodass diese Codes nicht in einem bestimmten Modell geschrieben werden.
Es kann sich beispielsweise um Backbone handeln, das in ViewController geschrieben ist ... Aber diese Wiederverwendung von Code ist nicht gut und die Ansicht wird durcheinander gebracht.
Meine aktuelle Lösung besteht darin, die meisten Modelloperationen in einer einzigen Datei zu sammeln, aber das Problem besteht darin, dass diese Datei immer größer und unübersichtlicher wird.
Wie soll ein solches Problem also gelöst werden?
Die erweiterte Frage lautet: Wie organisiert man diesen Teil des Codes?
Ich habe zum Beispiel die Flux-Lösung von React verwendet und versucht, den Prozess zu klären, stellte jedoch fest, dass ich nicht wusste, wo ich diesen Teil des Codes platzieren sollte..
Flux wandelt Benutzeroperationen in Aktionen um und Store überwacht diese Aktionen über den Dispatcher
Wenn eine Aktion mehreren Stores entspricht, tritt das Problem auf:
Sollte ich mehrere Aktionen verwenden, um jeweils den Stores zu entsprechen, oder sollte eine Aktion von mehreren Stores überwacht werden?
曾经蜡笔没有小新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。