#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
Каков наилучший способ сделать это? Вот все, что я мог придумать:
- Переопределить метод «set»
- Используйте «оптимизированную модель», которая прослушивает изменения в этой базовой модели и сохраняет очищенные входные данные. Затем весь код представления будет передан этой очищенной модели.
Конкретный пример «в нижнем регистре», который я упомянул, технически может быть лучше обработан представлением при его извлечении, но представьте себе другой случай, когда, скажем, пользователь вводит значения в фунтах, а я хочу хранить значения только в $ 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/13109723. проверка вызывается только для метода сохранения или если установлен параметр 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?