嵌套Backbone(Marionette)模型/集合中的冒泡事件 [英] Bubbling events in nested Backbone (Marionette) Models / Collections

查看:136
本文介绍了嵌套Backbone(Marionette)模型/集合中的冒泡事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个大型的木偶应用程序,它使用 Backbone.trackit 来监控模型中未保存的更改。



我们现在有一些嵌套模型,实际上我们有一个Model,带有一个模型集合,其中包含一个模型集合。



trackit 不支持在子模型更改时标记为脏的顶级模型 - 由于主干没有冒泡这些更改事件。



我知道我们可以手动监控这些变更事件,但我正在寻找通用解决方案。



有没有人有过以下libs或其他任何解决方案的经验?


  1. 骨干深度模型

  2. Backbone Associations活动

  3. 自定义Backbone.Model.set覆盖气泡更改事件

即时要求得到 trackit 使用嵌套事件 - 但我找不到任何分支到 trackit 添加它。



所以我想知道是否有人接近过这个,或者将上面的lib与 trackit 一起使用?



理想情况下,如果某个库在链条上一直触发标准的更改事件,那么 trackit 就会接受这个并开始工作。



所以,如果 model.countries [3] .regions [4] .name 已更改,更改:国家事件将在模型上触发。因此,如果模型具有 trackit enbaled,那么一切都会正常工作!

解决方案

默认情况下,集合中模型的事件已经冒泡到集合中。这样就解决了一件事,我们只需要从模型中的集合或其他模型中冒泡出事件。



我看到冒泡事件的一个问题 as-is 层次结构是当你想要听那个特定的集合或模型时,你会得到误报。



一种方式避免这是命名空间事件冒泡,但这可能不适用于 trackit



A简单实现一个模型,它可以冒泡任意集合或其他嵌套模型的事件:

  var BubblingModel = Backbone.Model.extend ({
/ **
*冒泡''对象'触发的任何事件。
* @param {Backbone.Events} obj实现Backbone事件。
* @param {String}键可选命名空间名称,默认为'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 中的任何事件都将以前缀为前缀其可选的或默认的嵌套字符串。由集合触发的更改:myAttribute 事件将是:

 optional-key:change:myAttribute

概念证明,简单测试:



  //简单的implementationvar BubblingModel = Backbone.Model.extend({/ ** *冒泡由'object'。* @param {Backbone.Events} obj触发的任何事件,它们实现了Backbone Events。* @param { String} key可选命名空间名称,默认为'nested'。* / addNested:function(obj,key){return this.listenTo(obj,'all',function(){arguments [0] =(key ||'nested ')+':'+ arguments [0]; this.trigger.apply(this,arguments);});},removeNested:func (obj){return this.stopListening(obj);使用多个nestingvar建立测试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}); //设置你想要冒泡.model3.addNested(model4,'model3-nested-model'); model2.addNested(col2,'model2-nested-col')。addNested(model5); model1.addNested(col1,'model1-nested-col') ; //从chainBackbone.listenTo(model2,'all',function(eventName){console.log(model2:,eventName);})中的任何模型中监听; Backbone.listenTo(model1,'all',function (eventName){console.log(model1:,eventName);}); //触发默认或自定义eventsmodel3.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>  


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 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?

  1. backbone-deep-model
  2. Backbone Associations events
  3. Custom Backbone.Model.set override that bubbles change events

The immediate requirement is to get trackit working with nested events - but I cant find any branches to trackit that add this.

So I was wondering if anyone has approached this, or used the above libs in conjunction with 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.

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.

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);
    }
});

and to use it:

var collection = new Backbone.Collection(),
    model = new BubblingModel();
model.addNested(collection, 'optional-key');

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"

Proof of concept with simple tests:

// 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆