Four Backbone.js Модельные вопросы - PullRequest
       0

Four Backbone.js Модельные вопросы

3 голосов
/ 02 сентября 2011

Я использую Backbone.js для отслеживания состояния в приложении визуализации.

Модель имеет такие атрибуты, как:

indicatorX : "income"
indicatorY : "emissions"
indicatorXScale : "lin"
indicatorYScale : "log"
year : 1980
layout : {leftPanel : {[...]}, rightPanel : {[...]}}  

1. Что такое хороший способ обработки "зависимых атрибутов" в модели Backbone.js?
Например, при изменении атрибута IndicatorX я бы также хотел, чтобы модель обновляла атрибут IndicatorXScale.

2. Как я могу обработать "задерживающиеся" атрибуты модели? Пример:

Модель содержит это:

indicatorX : "income"  
indicatorXScale : "log"

Если на модели установлен только индикаторX, для шкалы должно быть установлено значение по умолчанию:

model.set( {indicatorX : "emissions"} )
if("indicatorX" in changedAttrs){
    indicatorXScale = dataSource[indicatorX].defaultScale
}

Что, если, однако, пользователь захочет переопределить шкалу по умолчанию, которая в случае индикатора «эмиссии» является «lin»?

model.set( {indicatorX : "emissions", indicatorXScale : log} )

Поскольку атрибут атрибута модели XScale уже установлен в «журнал», измененный атрибут не записывается. Как я могу убедиться, что defaultScale не загружается в этом случае, а вместо этого передается в модель?

3. Является ли хорошей идеей позволить модели использовать дополнительный атрибут «действие» для описания изменений в модели?
Таким образом, контроллеры могут прослушивать один атрибут вместо указания обработчиков для комбинаций атрибутов. Вот альтернативы:

Alt 1. Контроллер имеет обработчики для определенных атрибутов:

this.model.bind("change:year", this.render);
this.model.bind("change:layout", this.updateLayout);  

Alt 2. Контроллер имеет обработчик для изменения модели и render () выясняет, что делать:

this.model.bind("change", this.render);
render() {
   var changedAttributes = this.model.changedAttributes
   if (a,b && c in changedAttributes) x()
   if (a,d in changedAttributes) y()
}

Alt 3. Позвольте модели описать, что означает комбинация изменений атрибутов:

this.model.bind("change:action", this.render);
render() {
   var changedAttributes = this.model.changedAttributes
   var action = this.model.get("action")
   if (action == gui_changeIndicator) x()
   if (action == gui_opacity) y()
}

4. Есть ли какие-либо подводные камни, на которые следует обратить внимание при использовании объектов в качестве атрибутов в модели Backbone.js?
Например, дорого ли выполнять isEqual для состояния макета, которое я пытаюсь сохранить в моей модели? Кроме того, при настройке модели объекты передаются по ссылке, поэтому для сравнения лучше использовать новый объект?

1 Ответ

10 голосов
/ 02 сентября 2011

1. Что такое хороший способ обработки «зависимых атрибутов» в модели Backbone.js? Например, при изменении атрибута IndicatorX, я бы также хотел, чтобы модель обновила атрибут IndicatorXScale.

ИМХО, расширьте модель и привяжите к событиям изменения. Например:

MyModel = Backbone.Model.extend({
    initialize: function() {
        this.bind('change:width', this.updateArea);
        this.bind('change:height', this.updateArea);
        this.updateArea();
    },
    updateArea: function () {
        this.area =  this.get('width') * this.get('height');
    }
});

var model = new MyModel({height: 10, width: 10});
console.log(model.area); //100
model.set({width: 15});
console.log(model.area); //150

Это довольно просто, но события изменения вызываются по ключу и в целом как «изменение»… так что вы можете связать их с определенными изменениями и при необходимости обновить. Если это большая модель с большим количеством ключей, которые периодически обновляются, то это определенно верный путь. Если это всего лишь эти две клавиши ... ну ... вы, вероятно, могли бы просто один раз связать с обычным событием изменения ".

2. Как я могу обрабатывать "устаревшие" атрибуты модели?

Переопределите метод set и добавьте свой собственный код. Пример:

MyModel = Backbone.Model.extend({
    constructor: function (obj) {
        this.touched = {}; //Set before the prototype constructor for anything being set
        Backbone.Model.prototype.constructor.call(this, obj);
        //set after for only things that the program has updated.
        return this;
    },
    set: function(attributes, options) {
        if(attributes.keyIWantToListenFor !== undefined && !this.touched.keyIWantToListenFor) {
            console.log("keyIWantToListenFor was set, let's fire off the right methods");
            this.touched.keyIWantToListenFor = true;
        }
        Backbone.Model.prototype.set.call(this, attributes, options);
        return this;
    }
});

var model = new MyModel({height: 10, width: 10});
model.set({keyIWantToListenFor: 15});

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

3. Является ли хорошей идеей позволить модели использовать дополнительный атрибут «действие» для описания изменений в модели?

Способ, которым пользователи Backbone настраивают его, заключается в том, что, как вы уже знаете, change: key специально для события change для определенного ключа. Полагаясь на действие change: action, вы как бы добавляете код 'gotcha!' В свой код. Я не вижу, как другие два метода лучше первого, особенно учитывая, что теперь у вас есть логика, брошенная в слушатель событий, чтобы определить, что нужно запустить ... вместо того, чтобы просто присоединять этот код непосредственно к соответствующим слушателям. Если бы у меня был выбор, я бы выбрал первый - это ясно: «Этот ключ обновлен, поэтому мы собираемся сделать X». Не "что-то обновилось, так что давайте выясним, что это такое!" и, возможно, придется пройти через дюжину операторов if или переключателей.

4. Есть ли какие-либо подводные камни, на которые следует обратить внимание при использовании объектов в качестве атрибутов в модели Backbone.js?

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

Объект по ссылке, безусловно, является проблемой - у меня есть небольшая дырка в стене, где я несколько раз пробивался головой, размышляя, почему что-то изменилось в совершенно не связанной… ох, подождите… Чтобы немного исправить это, вы можете переопределить метод get, чтобы в случаях, когда он возвращает объект, возвращать что-то вроде $ .extend (true, {}, this.get (key));

Кроме того, вы на самом деле не знаете, что именно изменилось в объекте на основе простого Backbone. Таким образом, если вы делаете много «материала» для изменения (перестройка представления и т. Д.), Вы потенциально столкнетесь с проблемами производительности, даже если все, что вы сделали, это добавили еще один атрибут к этому объекту, а это не так. используется для любого из указанных изменений. (т.е. set ({layout: layoutObj}) против set ({layoutPageTitle: 'blah'}), который может обновлять только заголовок .. вместо того, чтобы вызывать перезагрузку всего представления).

В противном случае, по крайней мере, в приложении, над которым я работаю, у нас не было реальных проблем с объектами в магистрали. Они синхронизируются довольно хорошо, и это, безусловно, лучше, чем .get ('layout.leftPanel [0]') и иметь какой-то волшебный перевод, чтобы это работало. Просто будьте осторожны с эталонной частью.

Надеюсь, это поможет хоть немного!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...