Backbone.js: Всегда определяйте, когда модель имеет установленный атрибут, а не только что/измененный.

В Backbone, когда я устанавливаю для атрибута модели то же значение, что и раньше, события «изменения» не запускаются.

Мой вид:

initialize: function() {
  this.$lastRollResult = this.$el.find('#lastRollResult');
  this.listenTo(this.model, 'change:lastRoll', this.render);
},

render: function() {
  this.$lastRollResult
    .html(this.model.get('lastRoll'))
    .addClass('shaking');

  var self = this;
  setTimeout(function() {
    self.$lastRollResult.removeClass('shaking');
  }, 1000);
},

events: {
  'click #button': function() {
    this.model.set('lastRoll', getRandomInteger(1, 6));
  }
}

Иногда, когда я вызываю getRandomInteger(), int будет таким же, как и предыдущий, из-за чего мой .set('lastRoll', int) не регистрируется как событие "изменения". Но это означает, что мой "трясущий" класс не будет применен, и это плохо.

Как заставить Backbone всегда распознавать установленный атрибут, даже если заданное значение было таким же? Есть ли какое-то "установленное" событие? (Не видел ни одного в документах.)

Редактировать: я знаю, что для этого, вероятно, существует хак {silent: true}/.trigger(), но есть ли какой-нибудь "чистый" или "семантический" способ всегда распознавать . вызов set()?


person Jackson    schedule 18.08.2013    source источник
comment
Нашел свой ответ в повторяющейся теме: stackoverflow.com/questions/15931233/   -  person Jackson    schedule 18.08.2013


Ответы (1)


Я думаю, что ваша конструкция неверна. Представление не должно выбирать случайное число и сообщать модели, что это ее новое значение, представление должно сообщать модели, что нужно свернуть новое число. Тогда вы могли бы иметь это в своей модели:

roll: function() {
    this.set('lastRoll', getRandomInteger(1, 6), { silent: true });
    this.trigger('change:lastRoll', this, this.get('lastRoll'));
}

и ваш взгляд будет просто this.model.roll(). Да, вы все еще занимаетесь {silent:true} и trigger хаком, но, по крайней мере, это будет в нужном месте.

Конечно, это может иметь странные побочные эффекты, так что вы можете зайти за спину модели и спокойно отменить значение, прежде чем устанавливать новое:

roll: function() {
    // I suppose you could quietly unset here if you feel bad
    // about fiddling with `attributes`.
    this.attributes.lastRoll = null;
    this.set('lastRoll', getRandomInteger(1, 6));
}

Опять же, наличие отдельного метода roll в модели — удобный способ скрыть все эти придирки от внешнего мира.

person mu is too short    schedule 18.08.2013
comment
Спасибо за предложение; Я позабочусь о том, чтобы почтить MV*. Также спасибо за подсказку о нескольких аргументах для trigger(), я не знал, что для этого требуется больше 1. Мне нравится предложение attribute.attribute = null, оно кажется самым быстрым, и мне нужно попробовать его (кажется немного схематично, но это может сработать...). - person Jackson; 18.08.2013
comment
Вы всегда молча отключаете его, если возня с attributes заставляет вас нервничать. - person mu is too short; 18.08.2013