Backbone.js 你怎么样';改变';主干模型中处理的事件?

Backbone.js 你怎么样';改变';主干模型中处理的事件?,backbone.js,model,meteor,Backbone.js,Model,Meteor,我试图构建一个模型,动态更新Meteor项目中的会话变量。我知道普通JSON不应该存储在主干模型中,所以我有一个特殊的模型,如下所示: initialize : function () { // Log the changed properties this.on('change', function (model, options) { for ( var i in options.changes) this.display(i);

我试图构建一个模型,动态更新Meteor项目中的会话变量。我知道普通JSON不应该存储在主干模型中,所以我有一个特殊的模型,如下所示:

initialize : function () {
    // Log the changed properties
    this.on('change', function (model, options) {
        for ( var i in options.changes)
            this.display(i);
        Session.set('NewSpecial', model);
    });
},
//Attributes
defaults: {
    "Product" : null,
    "ShortDescription" : null,
    "Category" : "food",
    "Price" : new PriceModel,
    "Date" : new DateModel,
    "Uses" : 0,
    "Tags" : [],
    "Contributor" : null
},
“价格”和“日期”存储在各自的型号中:

//Price model for use within Special
var PriceModel = Backbone.Model.extend({
    defaults : {
        "Regular" : null,
        "Special" : null,
        "PercentOff" : null
    }
});

//Date model for use within Special
var DateModel = Backbone.Model.extend({
    defaults : {
        "StartTime" : null,
        "EndTime" : null,
        "HumanTimeRange" : null
    }
});

如图所示,当特殊模型的属性更改时,它应该为更改的属性调用display,然后将会话变量设置为该模型。但是,如果我的DateModel或PriceModel发生更改,它似乎不会触发特殊模型上的更改事件。每个“DateModel”和“PriceModel”是否应该有自己的
this.on('change',…)
方法来调用
Special.set(attribute,thisModel)
方法?还是有不同的方法来解决这个问题?

我发现了几个问题

首先,您的
默认值是:

defaults: {
    "Product" : null,
    "ShortDescription" : null,
    "Category" : "food",
    "Price" : new PriceModel,
    "Date" : new DateModel,
    "Uses" : 0,
    "Tags" : [],
    "Contributor" : null
}
defaults: function() {
    return {
        "Product" : null,
        "ShortDescription" : null,
        "Category" : "food",
        "Price" : new PriceModel,
        "Date" : new DateModel,
        "Uses" : 0,
        "Tags" : [],
        "Contributor" : null
    };
}
这将导致该模型的所有实例共享一个
PriceModel
、一个
DateModel
、一个标签数组。对象被浅层复制并合并到模型的属性中,默认值中的任何值都不会被克隆或复制,它们只是按原样复制。如果您想要区分
价格
日期
标签
值,请使用
默认值
函数:

defaults: {
    "Product" : null,
    "ShortDescription" : null,
    "Category" : "food",
    "Price" : new PriceModel,
    "Date" : new DateModel,
    "Uses" : 0,
    "Tags" : [],
    "Contributor" : null
}
defaults: function() {
    return {
        "Product" : null,
        "ShortDescription" : null,
        "Category" : "food",
        "Price" : new PriceModel,
        "Date" : new DateModel,
        "Uses" : 0,
        "Tags" : [],
        "Contributor" : null
    };
}
第二个问题是,人们对变化的含义有着相当简单的看法。如果您查看,您将看到:

// If the new and previous value differ, record the change.  If not,
// then remove changes for this attribute.
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) !== _.has(prev, attr))) {
  this.changed[attr] = val;
  if (!silent) this._pending[attr] = true;
} else {
  delete this.changed[attr];
  delete this._pending[attr];
  if (!changing) delete this._changes[attr];
}
无法识别您的
价格
日期
中发生了更改,或者您从
标签
中添加或删除了某些内容。如果你这样做:

p = new PriceModel(...);
m.set('Price', p)
initialize: function() {
    this.attributes.Price.on(
        'all',
        function(ev, model, opts) { this.trigger(ev, model, opts) },
        this
    );
    //...
}
然后
m
会注意到
Price
已更改,但如果您:

p = m.get('Price');
p.set(...);
m.set('Price', p);
然后
m
将不会识别
Price
已更改;您的模型不会自动绑定到
Price
上的事件,因此它不会注意到
p.set(…)
调用,也不会将
m.set('Price',p)
识别为更改,因为这只不过是一种花哨的说法
p=p

您可以通过不给
set
一个来自
get
Tags
数组来解决部分更改问题;制作一份副本,更改副本,然后将更新后的副本交给
set
。这一半可以通过绑定到包含的
Price
Date
模型上的
“change”
事件来处理,并将其转发到类似于collections的方式,如下所示:

p = new PriceModel(...);
m.set('Price', p)
initialize: function() {
    this.attributes.Price.on(
        'all',
        function(ev, model, opts) { this.trigger(ev, model, opts) },
        this
    );
    //...
}
您希望提供自己的
实现,以防有人做了
集('Price',一些新对象)
,您需要重新绑定转发器