2012-05-01 4 views
17

Я ищу примеры для создания пользовательского конструктора на своих моделях. Я хочу, чтобы структура модели/данных была по-другому, а просто устанавливала ее как атрибуты.Пользовательский конструктор Backbone.js?

Может ли кто-нибудь показать мне некоторый базовый пример того, как это сделать?

Спасибо!

+1

Вы можете преобразовать JSON сервера при необходимости, используя 'parse' (http://documentcloud.github.com/backbone/#Model-parse). Возможно, вам следует уточнить, что вы пытаетесь сделать, пример может помочь. –

ответ

39

Если вы действительно хотите, чтобы переопределить конструктор, передать constructor свойства Backbone.Model.extend(), например:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    // ... 

    } 

}); 

Если вы хотите, чтобы вызвать встроенный конструктор от вашего пользовательского конструктора вы можете сделать что-то вроде:

var Klass = Backbone.Model.extend({ 

    constructor : function (attributes, options) { 

    Backbone.Model.apply(this, arguments); 

    } 

}); 

Или, если вы не хотите повторять имя va riable содержащего родительский класса во всем классе к югу, или вы не хотите, чтобы беспокоиться о значении этих переменных изменений, вы можете сделать что-то вроде следующий:

var Klass; 

var parent_klass = Backbone.Model.prototype; 

(function (parent_klass) { 

    Klass = parent_klass.constructor.extend({ 

    constructor : function (attributes, options) { 

     parent_klass.constructor.apply(this, arguments); 

    } 

    }); 

})(parent_klass); 

Или, если вы предпочитаете путь @Claude suggests, но повторять имя переменных подклассов в вспомогательном классе вместо имени класса вара родительского:

var Klass = Backbone.Model.extend(

    { 

    constructor : function (attributes, options) { 

     Klass.parent_klass.constructor.apply(this, arguments); 

    } 

    }, 

    { 

    parent_klass : Backbone.Model.prototype 

    } 

); 

Если вы хотите больше советов, чем это, вы должны быть более конкретными о том, что вы хотите достичь.

Все, что вы только хотите сделать после функциональности встроенного конструктора, вероятно, вы должны сделать в initialize().

+1

Будьте внимательны при использовании __super__ в сочетании с 'this'. 'this' всегда укажет на создаваемый объект, что приведет к бесконечному циклу. См. Мой ответ для получения дополнительной информации. – Claude

+0

@ Claude да, спасибо, что упомянули об этом. Я имел в виду обновить ответ re: that. Я перестал использовать '__super__' после публикации этого ответа. – JMM

+0

Как создать конструктор для каждого экземпляра модели с использованием прототипа? Я пытаюсь изменить метод конструктора при создании экземпляра Backbone.Model. Я хочу выполнить некоторую автоматическую привязку к работе с инфраструктурой socket.io узла. BuT Я не хочу прикладывать метод конструктора к каждой создаваемой модели. Добавление прототипа инициализации работ; единственная проблема - если кто-то передается с моделью, она переопределяет ее с помощью метода расширения подчеркивания. – kr1zmo

0

Похоже, что вы ищете метод initialize. Это называется, когда вы создаете новую модель, и вы можете использовать, если по каким-то вам это нужно:

var myModel = Backbone.Model.extend({ 
    initialize: function() { 
    // do something besides setting attributes or model 
    alert('myModel is ready for action!'); 
    } 
}); 

new myModel(); 

Если вы хотите сделать что-то более активное участие, вы можете переопределить метод constructor в ядре Backbone. Это гораздо более сложный бизнес. Гораздо лучше работать с открытыми методами, если можно!

+1

Я ищу пользовательский конструктор. Я не хочу, чтобы присваиваемые атрибуты просто устанавливались на модели. Я ищу, чтобы переопределить конструктор. – fancy

+1

Вы можете, конечно же, передать хэш хэш-функции 'initialize', манипулировать им внутри функции и задать любые необходимые вам атрибуты. – rjz

+0

«конструктор» «разоблачен», а документы объясняют, как вы можете его переопределить. 'initialize' служит другой цели. – Madbreaks

2

Если вы хотите, чтобы написать модель самостоятельно, как это:

var YourModel = function() { 
    // your constructor here 
}; 

_.extend(YourModel.prototype, Backbone.Model.prototype, { 
    // your model method here 
}); 

Будьте осторожны, я думаю, вам нужно проконсультироваться Backbone.Model конструктор source code. Но я думаю, что это не очень хорошая идея. Override initialize метода является правильным способом:

var YourModel = Backbone.Model.extend({ 
    initialize: function (attrs, options) { 
     Backbone.Model.prototype.initialize.apply(this, arguments); // call super constructor 

     // your constructor code here 
    } 
}); 
+0

Метод инициализации 'Backbone.Model' пуст, не уверен, что есть какая-то точка в его вызове. – raine

+0

@rane вы уверены, что это будет в будущих выпусках? Определенно разумно назвать супер метод. – Madbreaks

6

Это, как я переопределить Backbone.Model конструктор по умолчанию:

Backbone.Model = (function(Model) { 
    // Define the new constructor 
    Backbone.Model = function(attributes, options) { 
    // Your constructor logic here 
    // ... 
    // Call the default constructor if you wish 
    Model.apply(this, arguments); 
    // Add some callbacks 
    this.on('event', this.myCallback, this); 
    }; 
    // Clone static properties 
    _.extend(Backbone.Model, Model);  
    // Clone prototype 
    Backbone.Model.prototype = (function(Prototype) { 
    Prototype.prototype = Model.prototype; 
    return new Prototype; 
    })(function() {}); 
    // Update constructor in prototype 
    Backbone.Model.prototype.constructor = Backbone.Model; 
    return Backbone.Model; 
})(Backbone.Model); 

После этого вы должны убедиться, что прототип Backbone.Collection использует обновленный Backbone.Model конструктор:

_.extend(Backbone.Collection.prototype, { 
    model: Backbone.Model 
}); 

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

+1

+1 за то, что мои модели не расширили что-то еще – blockhead

7

Как я упоминаю в комментарии, позаботьтесь о том, чтобы использовать this.constructor.__super__ (или this.__super__), чтобы вы не оказались в бесконечном контуре (Maximum call stack size exceeded в Chrome).

Попробуйте следующее в консоли (на свой страх и риск, это приведет к упомянутому выше бесконечному циклу)

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    this.constructor.__super__.constructor.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    this.constructor.__super__.constructor.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// (8192) log: A 
// > RangeError: Maximum call stack size exceeded 

Причины в том, что при создании B, this в конструкторе A указует на экземпляр B , поэтому this.constructor.__super__.constructor продолжает указывать на конструктор A, который снова называется временем и временем.

Если вы хотите «намеченное поведение», используйте один из следующих синтаксисов:

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    A.__super__.constructor.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    B.__super__.constructor.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// log: A 
// > A.extend.constructor 

или непосредственно без __super__:

var A = Backbone.Model.extend({constructor: function() { 
    console.log("log: A"); 
    Backbone.Model.apply(this, arguments); 
}}); 

var B = A.extend({constructor: function() { 
    console.log("log: B"); 
    A.apply(this, arguments); 
}}); 

new A(); 
// log: A 
// > Backbone.model.extend.constructor 
new B(); 
// log: B 
// log: A 
// > A.extend.constructor 
-1

что-то, чтобы быть в курсе, когда переопределение конструктора Backbone.Model - если вы не вызываете Backbone.Model.apply, тогда Model.cid может не быть установлен.

Это плохо. Если cid не установлен на нескольких моделях, коллекция может считать его дубликат первой модели в вашей коллекции - и не позволит ее добавлять.

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