Backbone.js : 改变不触发 model.change() [英] Backbone.js : change not firing on model.change()
问题描述
我在 Backbone.js 上遇到了未触发更改事件"的问题 =/
I'm facing a "change event not firing" issue on Backbone.js =/
这是我对用户模型的看法:
Here my view of User model :
window.UserView = Backbone.View.extend({
...
initialize: function()
{
this.model.on('destroy', this.remove, this);
this.model.on('change', function()
{
console.log('foo');
});
},
render: function(selected)
{
var view = this.template(this.model.toJSON());
$(this.el).html(view);
return this;
},
transfer: function(e)
{
var cas = listofcas;
var transferTo = Users.getByCid('c1');
var transferToCas = transferTo.get('cas');
this.model.set('cas', cas);
console.log('current model');
console.log(this.model);
//this.model.change();
this.model.trigger("change:cas");
console.log('trigger change');
transferTo.set('cas', transferToCas);
console.log('transferto model');
console.log(transferTo);
//transferTo.change();
transferTo.trigger("change:cas");
console.log('trigger change');
}
});
这里是用户模型:
window.User = Backbone.Model.extend({
urlRoot: $('#pilote-manager-app').attr('data-src'),
initialize: function()
{
this.set('rand', 1);
this.set('specialite', this.get('sfGuardUser').specialite);
this.set('name', this.get('sfGuardUser').first_name + ' ' + this.get('sfGuardUser').last_name);
this.set('userid', this.get('sfGuardUser').id);
this.set('avatarsrc', this.get('sfGuardUser').avatarsrc);
this.set('cas', new Array());
if (undefined != this.get('sfGuardUser').SignalisationBouclePorteur) {
var cas = new Array();
_.each(this.get('sfGuardUser').SignalisationBouclePorteur, function(value)
{
cas.push(value.Signalisation);
});
this.set('cas', cas);
}
}
});
在用户模型中,有cas"属性,它是一个对象数组.
In User model, there is "cas" attribute, which is an array of objects.
我在其他主题中读到,如果属性不是值,则不会在 model.set 上触发更改事件.
I read in others topics that change events are not fire on model.set if attributes are not a value.
因此,我尝试使用 model.change() 方法直接触发更改事件.但是,我的控制台中没有foo"日志......
So, I try to trigger directly the change event with model.change() method. But, I have no "foo" log in my console ...
推荐答案
我对主干还很陌生,我也遇到了同样的问题.
I'm pretty new to backbone and I was having this same problem.
在做了一些研究之后,我发现了一些帖子更能说明为什么会发生这种情况,最终事情开始变得有意义了:
After doing some research, I found a few posts that shed a little bit more light on why this was happening, and eventually things started to make sense:
核心原因与引用相等与集合/成员相等的概念有关.在很大程度上,引用相等性似乎是主干用来确定属性何时发生更改的主要技术之一.
The core reason has to do with the notion of reference equality versus set/member equality. It appears that to a large extent, reference equality is one of the primary techniques backbone uses to figure out when an attribute has changed.
我发现,如果我使用诸如 Array.slice() 或 _.clone() 之类的技术来生成新引用,则可以识别更改事件.
I find that if I use techniques that generate a new reference like Array.slice() or _.clone(), the change event is recognized.
例如,以下代码不会触发事件,因为我正在更改相同的数组引用:
So for example, the following code does not trigger the event because I'm altering the same array reference:
this.collection.each(function (caseFileModel) {
var labelArray = caseFileModel.get("labels");
labelArray.push({ Key: 1, DisplayValue: messageData });
caseFileModel.set({ "labels": labelArray });
});
虽然这段代码确实触发了事件:
While this code does trigger the event:
this.collection.each(function (caseFileModel) {
var labelArray = _.clone(caseFileModel.get("labels")); // The clone() call ensures we get a new array reference - a requirement for the change event
labelArray.push({ Key: 1, DisplayValue: messageData });
caseFileModel.set({ "labels": labelArray });
});
注意:根据 Underscore API,_.clone() 通过引用复制某些嵌套项.不过,根/父对象是克隆的,因此它可以很好地用于主干.也就是说,如果您的数组非常简单并且没有嵌套结构,例如[1, 2, 3].
NOTE: According to the Underscore API, _.clone() copies certain nested items by reference. The root/parent object is cloned though, so it will work fine for backbone. That is, if your array is very simple and does not have nested structures e.g. [1, 2, 3].
虽然我上面改进的代码触发了更改事件,但以下没有因为我的数组包含嵌套对象:
While my improved code above triggered the change event, the following did not because my array contained nested objects:
var labelArray = _.clone(this.model.get("labels"));
_.each(labelArray, function (label) {
label.isSelected = (_.isEqual(label, selectedLabel));
});
this.model.set({ "labels": labelArray });
现在为什么这很重要?在非常仔细地调试之后,我注意到在我的迭代器中我正在引用同一个对象引用主干存储.换句话说,我不经意地把手伸进了模型的内部并翻转了一点.当我调用 setLabels() 时,主干正确地识别出没有任何变化,因为它已经知道我翻转了那个位.
Now why does this matter? After debugging very carefully, I noticed that in my iterator I was referencing the same object reference backbone was storing. In other words, I had inadvertently reached into the innards of my model and flipped a bit. When I called setLabels(), backbone correctly recognized that nothing changed because it already knew I flipped that bit.
在环顾四周之后,人们似乎普遍说 javascript 中的深复制操作是一种真正的痛苦 - 没有内置的东西可以做到这一点.所以我做了这个,这对我来说很好 - 一般适用性可能会有所不同:
After looking around some more, people seem to generally say that deep copy operations in javascript are a real pain - nothing built-in to do it. So I did this, which worked fine for me - general applicability may vary:
var labelArray = JSON.parse(JSON.stringify(this.model.get("labels")));
_.each(labelArray, function (label) {
label.isSelected = (_.isEqual(label, selectedLabel));
});
this.model.set({ "labels": labelArray });
这篇关于Backbone.js : 改变不触发 model.change()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!