Пользовательский конструктор Backbone.js?
Я ищу несколько примеров для создания пользовательского конструктора на своих моделях. Я хочу, чтобы структура модели/данных была по-разному, а затем просто устанавливала ее как атрибуты.
Может кто-нибудь показать мне некоторый базовый пример того, как это сделать?
Спасибо!
Ответы
Ответ 1
Если вы действительно хотите переопределить конструктор, передайте свойство 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 );
}
} );
Или, если вы не хотите повторять имя переменной, содержащей родительский класс, по всему подклассу, или вы не хотите беспокоиться о значении этой переменной, вы можете сделать что-то вроде следующее:
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 предлагает, но повторяя имя переменной подкласс в подклассе вместо родительского класса var name:
var Klass = Backbone.Model.extend(
{
constructor : function ( attributes, options ) {
Klass.parent_klass.constructor.apply( this, arguments );
}
},
{
parent_klass : Backbone.Model.prototype
}
);
Если вы хотите больше советов, чем это, вы должны быть более конкретными о том, чего вы хотите достичь.
Все, что вы хотите сделать только после встроенных функций конструктора, вероятно, вы должны сделать в initialize()
.
Ответ 2
Вот как я переопределяю конструктор 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 в качестве своего конструктора модели, что делает изменение более прозрачным.
Ответ 3
Как я упоминал в комментарии, будьте осторожны при использовании 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
Ответ 4
Если вы хотите написать свою модель самостоятельно, выполните следующие действия:
var YourModel = function () {
// your constructor here
};
_.extend(YourModel.prototype, Backbone.Model.prototype, {
// your model method here
});
Будьте осторожны, я думаю, вам нужно проконсультироваться с Backbone.Model
конструктором исходным кодом. Но я думаю, что это не очень хорошая идея. Метод 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
}
});
Ответ 5
Похоже, вы ищете метод 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. Тем не менее, это намного сложнее. Гораздо лучше работать с открытыми методами, если вы можете!
Ответ 6
Что-то нужно знать при переопределении конструктора Backbone.Model - если вы не вызываете Backbone.Model.apply
, тогда Model.cid может не быть установлен.
Это плохо. Если cid не задан в нескольких моделях, коллекция может считать это дубликат первой модели в вашей коллекции и не позволит ее добавлять.