【问题标题】:Bubbling events in nested Backbone (Marionette) Models / Collections嵌套主干(木偶)模型/集合中的冒泡事件
【发布时间】:2017-03-24 10:52:05
【问题描述】:

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

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

trackit 不支持在子模型更改时将顶级模型标记为“脏” - 因为主干不会冒泡这些更改事件。

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

有没有人对以下库或任何其他解决方案有任何经验?

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

当务之急是让 trackit 处理嵌套事件 - 但我找不到任何添加到 trackit 的分支。

所以我想知道是否有人处理过这个问题,或者将上述库与trackit 结合使用?

理想情况下,如果一个库会触发一个标准的“更改”事件,那么trackit 会接受这一点并开始工作。

因此,如果 model.countries[3].regions[4].name 更改,change:countries 事件将在 model 上触发。因此,如果模型有trackit enbaled,它就可以正常工作!

【问题讨论】:

标签: javascript backbone.js marionette backbone-events backbone.js-collections


【解决方案1】:

默认情况下,集合内模型的事件已经冒泡到集合中。所以这是一回事,我们只需要从集合或模型中的另一个模型中冒泡事件。

我在层次结构中按原样看到冒泡事件的一个问题是,当您想听那个特定的集合或模型时,您会得到误报。

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

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

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 事件将是:

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

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多