A simple way to make the nested object attribute trigger a change
event is to replace the whole object with the new one. The most straightforward way with a simple set
:
model.set('orderCondition', _.extend({}, model.get('orderCondition'), {
deliveryCostRequire: "TOTAL_ORDER_AMOUNT"
}));
Making a function to set nested attributes on the model is a good way to encapsulate that complexity.
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;
},
});
This is the basic concept.
Backbone.epoxy is a two-way binding library which also offers computed fields for models which achieves the same as above, but with the additional benefit of being completely transparent from outside the model.
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... */ },
}
});
With this model, you could do the following:
model.set('deliveryCostRequire', 'TOTAL_ORDER_AMOUNT');
model.get('deliveryCostRequire');
this.listenTo(model, 'change:deliveryCostRequire', this.render);
I also made a simple way to bubble up events of nested models and collections.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…