2013-11-14 3 views
0

Я столкнулся с очень неприятной ситуацией.По умолчанию значения backbone.js игнорируются, если атрибуты передаются при инициализации

Вот код инициализации модели:

var Model = Backbone.Model = function(attributes, options) { 
    var attrs = attributes || {}; 
    options || (options = {}); 
    this.cid = _.uniqueId('c'); 
    this.attributes = {}; 
    if (options.collection) this.collection = options.collection; 
    if (options.parse) attrs = this.parse(attrs, options) || {}; 
    attrs = _.defaults({}, attrs, _.result(this, 'defaults')); 
    this.set(attrs, options); 
    this.changed = {}; 
    this.initialize.apply(this, arguments); 
}; 

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

Логическое мышление Я бы ожидал, что значения по умолчанию всегда устанавливаются в самом начале инициализации, а затем значения будут заменены, когда метод «set» вызывается таким образом, что я мог бы переопределить метод «set» для обработки атрибутов типа массива и преобразования их для коллекции, как так:

set: function() { 
    var firstArgument = arguments[0], 
     attributesMap; 
    if (_.isObject(firstArgument)) { 
     //setting with attributes map 
     attributesMap = firstArgument; 
     _.each(attributesMap, function (value, attribute) { 
      var modelAttribute = this.attributes[attribute]; 
      if (modelAttribute && modelAttribute instanceof Backbone.Collection) { 
       modelAttribute.reset(value); 
       delete attributesMap[attribute]; 
      } 
     }, this); 
    } 

    return Backbone.Model.prototype.set.apply(this, arguments); 
} 

Теперь то, что я делаю - это проверка, если атрибут по умолчанию является экземпляром Backbone.Collection и если да сбросить коллекцию с заданными значениями массива (сохраняя ту же ссылку сбора и позволяя взгляды или другие объекты данных для прослушивания этой коллекции) и не допускать перезаписывания с помощью обычного массива.

Из-за проблемы, описанной ранее при вызове метода «set», у нее нет атрибутов по умолчанию, и я не могу проверить, какой тип атрибута я хочу манипулировать.

Как вы относитесь к атрибутам, которые являются массивами, и которые должны быть преобразованы и обработаны как Backbone.Collection?

На данный момент я только что изменил функцию «по умолчанию» делать, и вместо того, чтобы возвращать атрибуты объекта я делаю это:

defaults: function() { 
    this.attributes = { 
     ... 
    }; 
} 
+0

Посмотрите, понимаю ли я это правильно. Обычно, когда вы передаете атрибуты при инициализации, они переопределяют значения по умолчанию, но вы хотите, чтобы значения по умолчанию оставались в такте? – GijsjanB

+0

Нет. Я хочу, чтобы значения по умолчанию были установлены при инициализации непосредственно перед тем, как метод «set» вызывается так, когда я переопределяю метод «set». Я могу проверить тип атрибута. И значения по умолчанию будут перезаписаны при вызове метода «set». Теперь поток: 1) Создайте модель 2) Проверьте, соответствуют ли переданные атрибуты всем значениям, которые определены с «значениями по умолчанию» и слияния с отсутствующими 3) Метод набора вызовов Я бы предпочел следующее: 1) Создать модель 2) Установить значения по умолчанию 3) Метод набора вызовов и переопределить эти значения тем, что у вас есть. –

+0

Я не понимаю, что вы пытаетесь сделать и почему, извините. – GijsjanB

ответ

0

Это взято из источников Backbone

var Model = Backbone.Model = function(attributes, options) { 
    var attrs = attributes || {}; 
    options || (options = {}); 
    this.cid = _.uniqueId('c'); 
    this.attributes = {}; 
    if (options.collection) this.collection = options.collection; 
    if (options.parse) attrs = this.parse(attrs, options) || {}; 
    attrs = _.defaults({}, attrs, _.result(this, 'defaults')); // (1) 
    this.set(attrs, options);  
    this.changed = {}; 
    this.initialize.apply(this, arguments); 
}; 

Как вы можете видеть на (1), он использует значение подчеркивания по умолчанию, которое просто объединяет объекты, переопределяющие, перед вызовом set.

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

... 
    if (options.parse) attrs = this.parse(attrs, options) || {}; 

    this.set(_.result(this, 'defaults') , options); // set the default attrs 
    this.changed = {}; 
    this.set(_.defaults({}, attrs) , options);  // set the attrs as passed in arguments 
    this.initialize.apply(this, arguments); 
}; 

Это, конечно, будет чище, чтобы определить новую модель и оставить источник магистральную нетронутым.

Кроме того, хотя я могу догадаться, что вы хотите сделать, я думаю, вы должны рассмотреть другой путь к нему.

Надеюсь, что помощь!

Смежные вопросы