监听嵌套模型属性的变化

Listen to changes from nested model attributes

我有一个模型属性,它是一个对象:

name : "testing",
orderCondition: {
  minOrderAmount: 20, 
  deliveryCostRequire: "MIN_ORDER_AMOUNT", 
  deliveryCostAmount: 5.55
}

当我这样使用listenTo时,render函数没有被调用

this.listenTo(this.model, "change:orderCondition", this.render); // NO FIRING

但是当我在其他属性上使用 listenTo 时,它起作用了。

this.listenTo(this.model, "change:name", this.render); // FIRING

为什么 listenTo 看不到嵌套对象的变化但在简单属性中看到它们?

只是因为 Backbone 不适用于嵌套对象。例如,您不能通过 model.set().

set 对象 属性 的属性

您的 this.listenTo 只监听整个对象的变化,而不是它的属性。

您可以尝试使用 backbone-deep-model 等库来支持嵌套对象。

使嵌套对象属性触发 change 事件的一种简单方法是用新对象替换整个对象。最简单的方法是 set:

model.set('orderCondition', _.extend({}, model.get('orderCondition'), {
    deliveryCostRequire: "TOTAL_ORDER_AMOUNT"
}));

创建一个函数来设置模型的嵌套属性是封装这种复杂性的好方法。

var Model = Backbone.Model.extend({

    setDeliveryCostRequire: function(value, options) {
        // build a new object for 'orderCondition'
        var newOrderCondition = _.extend({}, this.get('orderCondition'), {
            deliveryCostRequire: value
        });
        // replace 'orderCondition' with the new object.
        this.set({ orderCondition: newOrderCondition }, options);
        // optionally trigger a custom event for it.
        this.trigger('change:deliveryCostRequire', this, value, options);
        return this;
    },
});

这是基本概念。

Backbone.epoxy 是一个 two-way 绑定库,它还为模型提供计算字段,实现与上述相同的效果,但具有对模型外部完全透明的额外好处。

var Model = Backbone.Model.extend({
    computeds: {
        deliveryCostRequire: {
            deps: ['orderCondition'],
            get: function(orderCondition) {
                return orderCondition && orderCondition.deliveryCostRequire;
            },
            set: function(value) {
                return {
                    orderCondition: _.extend({}, this.get('orderCondition'), {
                        deliveryCostRequire: value
                    })
                };
            },
        },
        deliveryCostAmount: { /* ...other computed... */ },
    }
});

使用此模型,您可以执行以下操作:

model.set('deliveryCostRequire', 'TOTAL_ORDER_AMOUNT');
model.get('deliveryCostRequire');
this.listenTo(model, 'change:deliveryCostRequire', this.render);

我也做了a simple way to bubble up events of nested models and collections.