骨干模型只发生一次变化

时间:2016-08-09 10:13:20

标签: javascript backbone.js marionette backbone-model

当您创建Backbone模型并附加更改事件时,它将监听它。如果您同时更改它们(在相同的设置调用中),它将触发更改事件您模型中的更改次数。

想象一下,我的视图就像一个带过滤器的网格,每次更改过滤器时都必须刷​​新。

我的默认模型如下所示:

versionCode

我在视图中有一个模型的监听器:

defaults: {
    filters: {
        from: '2016-01-01',
        to: today.format(format),
        limit: 25,
        page: 1,
        cycle: 'all'
    }
},

每次我更换过滤器时都会这样做:

this.listenTo(this.model, 'change:filters', this.onShow);

如您所见,我已更改此模型的3个属性。会发生什么事情,它将触发变化事件3次。 我想要实现的是它只会改变一次,即使我对模型进行了3次更改。

可行吗?

提前致谢

3 个答案:

答案 0 :(得分:0)

来自Backbone文档:

  

"变化:[属性]" (model,value,options) - 更新特定属性时。

在您的案例中,模型有一个属性:filters。如果为此属性设置新值(无论是object,array,int,float,string)事件都将被触发。只有一次。

如果您需要观察属性值的修改,您必须编写自己的处理程序。

this.listenTo(this.model, 'change:filters', function(model, value) {
    prev = model.previous('filters');
    if(prev.from != value.from) model.trigger('change:filters:from', model, value.from);
    if(prev.to != value.to) model.trigger('change:filters:to', model, value.to);
    if(prev.limit != value.limit) model.trigger('change:filters:limit', model, value.limit);
    if(prev.page != value.page) model.trigger('change:filters:page', model, value.page);
    if(prev.cycle != value.cycle) model.trigger('change:filters:cycle', model, value.cycle);
});

并在代码中:

this.listenTo(this.model, 'change:filters:from', this.onShow);
this.listenTo(this.model, 'change:filters:to', this.onShow);
this.listenTo(this.model, 'change:filters:limit', this.onShow);
this.listenTo(this.model, 'change:filters:page', this.onShow);
this.listenTo(this.model, 'change:filters:cycle', this.onShow);

答案 1 :(得分:0)

我经常遇到这种情况,主要是在使用Marionette的Collection或CompositeViews并听取基础集合的变化时。通常情况下,会更新多个子模型,并且需要重新渲染或重新排序CompositeView,但我不想为每个子模型更改重新渲染/重新排序 - 只是一旦同时发生一个或多个变化。我使用如下的setTimeout处理了这个:

var MyView = Backbone.Marionette.CompositeView.extend({
    childView: ChildView,
    initialize: function() {
        this.listenTo(this.collection, 'change', this.onChildModelChanged);
        this.childModelChanged = false;
    },
    onChildModelChanged: function() {
        // use a setTimeout 0 so that we batch 'changes' and re-render once
        if(this.childModelChanged === false) {
            this.childModelChanged = true;
            setTimeout(function() {
                this.render();
                this.childModelChanged = false;
            }.bind(this), 0);
        }
    }
});

这允许在重新渲染或重新排序之前触发所有子模型更改事件。希望这会有所帮助。

答案 2 :(得分:0)

认为这将是有问题的场景的黑客攻击。您可以在模型上定义自定义事件。

  • 收听模型change-filters
  • 上的自定义事件
  • 在设置模型时传递选项silent : true
  • 如果有任何更改的属性,则触发模型上的自定义事件。