Can I force an update to a model's attribute t

2019-05-02 10:54发布

问题:

I know that I can set the value of a Backbone model's attribute so that it doesn't trigger a change event using {silent:true}. I also know that if I set a model's attribute to a value it already has, it won't trigger a change event, which is almost always a good thing. However, is there a way to force the update to the model to trigger a change event even if it's set to the same value?

So if within my model I have set:

defaults:{
    attributeToChange: "myValue"
}

And then in the a view using this model I call:

this.model.set('attributeToChange', 'myNewValue', {silent:true});

the value will change but no change event will be fired. But what if I wanted to have a change event fired whenever the attribute's value was set, regardless of what it was set to? So if instead I just did

this.model.set('attributeToChange','myValue');

is there a parameter I can add that will force this to be seen as a change? I believe that I can use

this.model.trigger('change:attributeToChange');

but I'd like to know if there's a way to force the change event to fire without this.

Bonus question: If I set a model's attribute to a value it already has, does this make the attribute's previous value the value it had before I initiated the change?

this.model.set('attributeToChange','someValue');
this.model.set('attributeToChange','anotherValue');
this.model.set('attributeToChange','anotherValue');
console.log(this.model.previous('attributeToChange')); //someValue or anotherValue?

回答1:

When you set a value to a model in Backbone, Backbone will compare the new value to the current ones, and add the changed values to an array (see https://github.com/documentcloud/backbone/blob/master/backbone.js#L342).

Then, if the changes array contains element, Backbone will triggers the "change:{key}" event for each changed item if silent is not set to true. (see https://github.com/documentcloud/backbone/blob/master/backbone.js#L357).

Finally, it will also trigger the global "change" event (again, if silent is not set to true).

So if you want to force the trigger on non-changed attributes, you can manually trigger the event, like Backbone does, or override the set method like @Loamhoof suggested.



回答2:

Sadly, there is nothing here. I guess you could change the code of the set method, but it'd be pretty ugly. Another solution would be to override it at the beginning, or the end (that's the "easy" changes you can do to override a method).

For the beginning, the problem is that your attributes aren't set yet (and aren't validated neither).
So, let's see for the end.

var set = Backbone.Model.prototype.set;
Backbone.Model.prototype.set = function() {
  // do stuff before
  set.apply(this, arguments);
  // do stuff after
  this.trigger('myCustomEvent');
  return this;
};

(I don't think you'd have to do it before defining your models, but it may be.)



回答3:

I had this problem when I set to existed model atrribute another object, that has same keys and values. That was different object, but model didn't trigger "change" event. So for this problem I've used such solution: I set attributes to model in "silent" mode and after that I triggered "change"-event for particular atrribute. e.g.

this.model.set({currentPage: page,
                currentPanel: panel}, {silent:true});
this.model.trigger('change:currentPanel');


标签: backbone.js