嵌套 Backbone (Marionette) 模型/集合中的冒泡事件 [英] Bubbling events in nested Backbone (Marionette) Models / Collections
问题描述
我们有一个大型 Marionette 应用程序,它使用 Backbone.trackit
来监控模型中未保存的更改.
We have a large Marionette App, that uses Backbone.trackit
to monitor unsaved changes in our Models.
我们现在有一些嵌套模型,实际上我们有一个模型,其中包含一个模型集合,其中包含一个模型集合.
We now have some nested models, in fact we have a Model, with a Collection of Models, that contain a Collection of Models.
trackit
不支持在子模型更改时将顶级模型标记为脏" - 由于主干不会冒泡这些更改事件.
trackit
doesn't support the top level model being marked as 'dirty' when the child models change - due to backbone not bubbling these change events.
我知道我们可以手动监控这些更改事件,但我正在寻找通用的解决方案.
I know we could manually monitor these change events, but Im looking for a generic solution.
有没有人对以下库或任何其他解决方案有任何经验?
Has anyone had any experience of the following libs or any other solutions for this?
当务之急是让 trackit
处理嵌套事件 - 但我找不到任何添加此内容的 trackit
分支.
The immediate requirement is to get trackit
working with nested events - but I cant find any branches to trackit
that add this.
所以我想知道是否有人解决过这个问题,或者将上述库与 trackit
结合使用?
So I was wondering if anyone has approached this, or used the above libs in conjunction with trackit
?
理想情况下,如果一个库会在整个链中触发一个标准的更改"事件,那么 trackit
就会注意到这一点并开始工作.
Ideally, if a library would trigger a standard 'change' event all the way up the chain, then trackit
would just pick up on this and start working.
因此,如果 model.countries[3].regions[4].name
改变,change:countries
事件将在 model上触发代码>.因此,如果模型启用了
trackit
,它就可以正常工作!
so, if model.countries[3].regions[4].name
changed, a change:countries
event would be triggered on model
. Thus if the model had trackit
enbaled, it would all just work!
推荐答案
默认情况下,来自集合内模型的事件已经冒泡到集合中.所以这是一件事解决了,我们只需要从集合或模型中的另一个模型中冒泡事件.
The events from models inside a collection already bubbles to the collection by default. So that's one thing solved and we just need to bubble events from a collection or another model inside a model.
我在层次结构中原样看到的冒泡事件的一个问题是,当您想收听那个特定集合或模型时,您会得到误报.
One problem I see with bubbling events as-is up the hierarchy is that you then get false positive when you want to listen to that specific collection or model.
避免这种情况的一种方法是冒泡的命名空间事件,但这可能不适用于 trackit.
A way to avoid that is to namespace events that are bubbling up, but that may not work with trackit.
一个模型的简单实现,它可以使任意集合或其他嵌套模型的事件冒泡:
A simple implementation of a model that enables bubbling up events of arbitrary collections or other nested models:
var BubblingModel = Backbone.Model.extend({
/**
* Bubbles up any event triggered by 'object'.
* @param {Backbone.Events} obj which implement the Backbone Events.
* @param {String} key optional namespace name, default to 'nested'.
*/
addNested: function(obj, key) {
return this.listenTo(obj, 'all', function() {
arguments[0] = (key || 'nested') + ':' + arguments[0];
this.trigger.apply(this, arguments);
});
},
removeNested: function(obj) {
return this.stopListening(obj);
}
});
并使用它:
var collection = new Backbone.Collection(),
model = new BubblingModel();
model.addNested(collection, 'optional-key');
来自 collection
的任何事件都将以其可选的 key
或默认的 nested
字符串作为前缀.collection
触发的 change:myAttribute
事件将是:
Any events from collection
will be prefixed by its optional key
or by the default nested
string. A change:myAttribute
event triggered by collection
would be:
"optional-key:change:myAttribute"
概念验证,通过简单的测试:
// The simple implementation
var BubblingModel = Backbone.Model.extend({
/**
* Bubbles up any event triggered by 'object'.
* @param {Backbone.Events} obj which implement the Backbone Events.
* @param {String} key optional namespace name, default to 'nested'.
*/
addNested: function(obj, key) {
return this.listenTo(obj, 'all', function() {
arguments[0] = (key || 'nested') + ':' + arguments[0];
this.trigger.apply(this, arguments);
});
},
removeNested: function(obj) {
return this.stopListening(obj);
}
});
// Setting up a test with multiple nesting
var model5 = new Backbone.Model(),
model4 = new Backbone.Model(),
model3 = new BubblingModel({ model: model4 }),
col2 = new Backbone.Collection([model3]),
model2 = new BubblingModel({ col: col2 }),
col1 = new Backbone.Collection([model2]),
model1 = new BubblingModel({ col: col1 });
// Set which you want to bubble up.
model3.addNested(model4, 'model3-nested-model');
model2.addNested(col2, 'model2-nested-col')
.addNested(model5);
model1.addNested(col1, 'model1-nested-col');
// listen from any model down the chain
Backbone.listenTo(model2, 'all', function(eventName) {
console.log("model2:", eventName);
});
Backbone.listenTo(model1, 'all', function(eventName) {
console.log("model1:", eventName);
});
// trigger default or custom events
model3.set('test', 1);
model3.trigger('model3');
model4.trigger('model4');
model5.trigger('model5');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
这篇关于嵌套 Backbone (Marionette) 模型/集合中的冒泡事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!