如何在骨干模型处理“变”事件? [英] How are 'change' events handled in backbone models?

查看:130
本文介绍了如何在骨干模型处理“变”事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立一个模型,在流星项目动态更新会话变量。我知道,普通的JSON不宜存放骨干模型中,让我有一种特殊的模型建立像这样:

I'm trying to build a model that dynamically updates Session variables in a Meteor project. I know that plain JSON should not be stored within backbone models, so I have a Special model set up like so:

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
},

使用价格和日期被存储在自己的模式:

With "Price" and "Date" being stored in their own models:

//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
    }
});

如图所示,当特殊模式变革的属性,就应该要求变更了的属性显示,然后会话VAR设置为模型。但是,如果我DateModel或PriceModel改变,它不会出现触发特殊模型的变化事件。如果每个DateModel和PriceModel有自己的 this.on('变化',...)调用方法 Special.set(属性,thisModel)的方法呢?还是有不同的方式去了解呢?

As shown, when the attributes of the Special model change, it should call display for the attribute that changed, and then set the Session var to the model. If my DateModel or PriceModel change however, it doesn't appear to trigger a change event on the Special model. Should each "DateModel" and "PriceModel" have their own this.on('change', ...) methods that call Special.set(attribute, thisModel) methods? Or is there a different way to go about this?

推荐答案

我看到一对夫妇的问题。

I see a couple problems.

首先,你的默认

defaults: {
    "Product" : null,
    "ShortDescription" : null,
    "Category" : "food",
    "Price" : new PriceModel,
    "Date" : new DateModel,
    "Uses" : 0,
    "Tags" : [],
    "Contributor" : null
}

这将最终有一个 PriceModel ,一是 DateModel ,和一个标签阵列被所有实例共享该模型。一个 默认 对象浅拷贝并合并成模型的属性,没有值的默认克隆或复制,他们只是复制了原样。如果你想distinced 价格日期标签值然后使用默认功能:

That will end up with one PriceModel, one DateModel, and one tags array being shared by all instances of that model. A defaults object is shallow copied and merged into the model's attributes, none of the values in defaults are cloned or duplicated, they're just copied over as-is. If you want distinced Price, Date, and Tags values then use a function for defaults:

defaults: function() {
    return {
        "Product" : null,
        "ShortDescription" : null,
        "Category" : "food",
        "Price" : new PriceModel,
        "Date" : new DateModel,
        "Uses" : 0,
        "Tags" : [],
        "Contributor" : null
    };
}

第二个问题是, 设置 有什么样的变更的意味着一个相当简单化的看法。如果你看一下设置 ,你会看到这一点:

The second problem is that set has a fairly simplistic view of what change means. If you have a look at the source for set, you'll see this:

// 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];
}

_。isEqual:方法 将无法识别有什么东西你的价格日期内改变或你已经添加或从标签。如果你做这样的事情:

The _.isEqual won't recognize that something has changed inside your Price or Date or that you've added or removed something from Tags. If you do things like this:

p = new PriceModel(...);
m.set('Price', p)

然后 M 会注意到价格已更改,但如果您:

then m will noticed that Price has changed but if you:

p = m.get('Price');
p.set(...);
m.set('Price', p);

然后 M 将无法识别价格已经改变;你的模式不会自动绑定到事件的价格所以它不会注意到 P.SET(...)打电话,也不会承认 m.set('价格',p)作为自认为的变化比一个奇特的方式多一点说的 p =

then m won't recognize that Price has changed; your model won't automatically bind to events on Price so it won't notice the p.set(...) call and it won't recognize m.set('Price', p) as a change since that's little more than a fancy way of saying p = p.

您可以解决这个问题的变化的一部分的不给问题设置 A 标签 GET 来到阵列;做一个副本,改变副本,然后用手将更新的副本。半可以通过在包含价格日期结合改变事件处理模型,并在转发类似藏品如何做到这一点,是这样的:

You can solve part of this change problem by not giving set a Tags array that came from get; make a copy, change the copy, and then hand the updated copy to set. The half can be handled by binding to "change" events on the contained Price and Date models and forwarding them similar to how collections do it, something like this:

initialize: function() {
    this.attributes.Price.on(
        'all',
        function(ev, model, opts) { this.trigger(ev, model, opts) },
        this
    );
    //...
}

您会希望提供自己的设置万一有人实施做了设置('价格',some_new_object),你需要重新绑定您的转发器。

You'd want to provide your own set implementation in case someone did a set('Price', some_new_object) and you need to rebind your forwarder.

这篇关于如何在骨干模型处理“变”事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆