Backbone.js — пользовательские сеттеры

#javascript #backbone.js

#javascript #backbone.js

Вопрос:

Представьте себе простую модель магистрали, например

 window.model= Backbone.Model.extend({
   defaults:{
      name: "",
      date: new Date().valueOf()
   }
})
  

Я пытаюсь найти способ всегда заставлять модель сохранять имя в нижнем регистре независимо от предоставленного ввода. т.е.,

 model.set({name: "AbCd"})
model.get("name") // prints "AbCd" = current behavior
model.get("name") // print "abcd" = required behavior
  

Каков наилучший способ сделать это? Вот все, что я мог придумать:

  1. Переопределить метод «set»
  2. Используйте «оптимизированную модель», которая прослушивает изменения в этой базовой модели и сохраняет очищенные входные данные. Затем весь код представления будет передан этой очищенной модели.

Конкретный пример «в нижнем регистре», который я упомянул, технически может быть лучше обработан представлением при его извлечении, но представьте себе другой случай, когда, скажем, пользователь вводит значения в фунтах, а я хочу хранить значения только в $ s в моей базе данных. Также могут быть разные представления для одной и той же модели, и я не хочу делать «toLowerCase» везде, где он используется.

Мысли?

Ответ №1:

ОБНОВЛЕНИЕ: вы можете использовать плагин: https://github.com/berzniz/backbone.getters.setters


Вы можете переопределить метод set следующим образом (добавьте его в свои модели):

 set: function(key, value, options) {
    // Normalize the key-value into an object
    if (_.isObject(key) || key == null) {
        attrs = key;
        options = value;
    } else {
        attrs = {};
        attrs[key] = value;
    }

    // Go over all the set attributes and make your changes
    for (attr in attrs) {
        if (attr == 'name') {
            attrs['name'] = attrs['name'].toLowerCase();
        }
    }

    return Backbone.Model.prototype.set.call(this, attrs, options);
}
  

Комментарии:

1. вместо цикла я бы рекомендовал, если(attrs.name )attrs.name = attrs.name.toLowerCase();

2. Обратите внимание, что если первый параметр является объектом, настройка атрибутов делегируется set с помощью строки в качестве первого параметра. Таким образом, нормализация необходима только в том случае, если первый параметр является строкой.

Ответ №2:

Это был бы взлом, потому что это не то, для чего он был создан, но вы всегда можете использовать для этого валидатор:

 window.model= Backbone.Model.extend({
   validate: function(attrs) {
      if(attrs.name) {
         attrs.name = attrs.name.toLowerCase()
      }

      return true;
   }
})
  

Функция validate будет вызвана (до тех пор, пока silent опция не установлена) до того, как значение будет установлено в модели, поэтому это дает вам возможность изменить данные до того, как они будут действительно установлены.

Комментарии:

1. Спасибо. Я тоже рассматривал это, но это, казалось, было шагом назад с точки зрения удобства чтения — переопределение функции set или добавление новой функции «setProperty», которая устанавливает ее в нижнем регистре, а затем передает ее в набор backbone, может быть лучше. Если я чего-то не упускаю?

2. Конечно, нет ничего плохого в переопределении set метода для выполнения того, что вам нужно сделать … некоторая предварительная обработка перед набором? Вы могли бы даже рассмотреть возможность расширения Backbone.Model.prototype.set для вызова некоторых предварительных процессоров, если они совпадают … что-то вроде этого: gist.github.com/1310972

3. проверка вызывается только для метода сохранения или если установлен параметр options.validate = true . (здесь не используется silent, но ответ довольно старый)

Ответ №3:

Не для того, чтобы сигналить самому себе, но я создал базовую модель с «вычисляемыми» свойствами, чтобы обойти это. Другими словами

 var bm = Backbone.Model.extend({
  defaults: {
     fullName: function(){return this.firstName   " "   this.lastName},
     lowerCaseName: function(){
        //Should probably belong in the view
        return this.firstName.toLowerCase();  

     }
   }
})
  

Вы также прослушиваете изменения в вычисляемых свойствах и в значительной степени просто рассматриваете это как обычное.

Упомянутый плагин Bereznitskey также является допустимым подходом.

Комментарии:

1. Я пытаюсь сделать это сейчас, и это повторяет мою фактическую функцию, а не возвращаемое значение. defaults: { distance: function() { return 10; } }, тогда console.log(this.model.get('distance')); ??

2. @trapper — вы расширяете «BasecomputedModel» из связанного github?