Backbone.js view inheritance

Tengo una vista llamada Pannel que es solo un fondo con un botón de cerrar. Quiero extender esa vista a una llamada PannelAdvanced . ¿Cómo haría eso con backbone.js?

En este momento, todos los ejemplos tienen Backbone.View.Extend pero solo extienden Backbone.View ; Quiero extender mi PannelView .

La forma más fácil de heredar una vista es hacer lo que otras personas ya han sugerido en los comentarios:

 var Pannel = Backbone.View.extend({ }); var PannelAdvanced = Pannel.extend({ }); 

Pero como ha notado en sus comentarios, si tiene un método de inicialización en Pannel, no se llamará si también tiene un método de inicialización en PannelAdvanced, por lo que debe llamar al método de inicialización de Pannel explícitamente:

 var Pannel = Backbone.View.extend({ initialize: function(options){ console.log('Pannel initialized'); this.foo = 'bar'; } }); var PannelAdvanced = Pannel.extend({ initialize: function(options){ Pannel.prototype.initialize.apply(this, [options]) console.log('PannelAdvanced initialized'); console.log(this.foo); // Log: bar } }); 

Es un poco feo porque si tienes muchas Vistas heredadas de Pannel, entonces tendrás que recordar llamar a la inicialización de Pannel de todas ellas. Peor aún, si Pannel no tiene un método de inicialización ahora pero decide agregarlo en el futuro, necesitará ir a todas las clases heredadas en el futuro y asegurarse de que invoquen la inicialización de Pannel. Así que aquí hay una forma alternativa de definir Pannel para que sus vistas heredadas no necesiten llamar al método de inicialización de Pannel:

 var Pannel = function (options) { // put all of Panel's initialization code here console.log('Pannel initialized'); this.foo = 'bar'; Backbone.View.apply(this, [options]); }; _.extend(Pannel.prototype, Backbone.View.prototype, { // put all of Panel's methods here. For example: sayHi: function () { console.log('hello from Pannel'); } }); Pannel.extend = Backbone.View.extend; // other classes inherit from Panel like this: var PannelAdvanced = Pannel.extend({ initialize: function (options) { console.log('PannelAdvanced initialized'); console.log(this.foo); } }); var pannelAdvanced = new PannelAdvanced(); //Log: Pannel initialized, PannelAdvanced initialized, bar pannelAdvanced.sayHi(); // Log: hello from Pannel 

Esta es una de las razones por las que me gusta mucho usar Coffeescript. Cosas como la herencia son mucho más agradables. Para aprovechar la respuesta correcta de @JohnnyO, puedo decir lo mismo en Coffeescript:

 class Panel extends Backbone.View initialize: -> console.log 'Panel initialized' @foo = 'bar' class PanelAdvanced extends Panel initialize: -> super console.log 'PanelAdvanced initialized' console.log @foo 

Para aprovechar un poco más:

Me gustó el enfoque de @JohnnyO, pero quería confirmar que una vista resultante todavía era capaz de hacer todo lo que se supone que debe hacer. Dado su enfoque, no sospeché que hubiera ningún problema, pero quería estar un poco más seguro.

Entonces, me tomé un minuto y adapté el conjunto de pruebas de Backbone.js Views a la técnica de herencia múltiple que propone @JohnnyO.

Puede ejecutar los resultados en http://jsfiddle.net/dimadima/nPWuG/ . Todas las pruebas pasan

Mi base y vistas extendidas:

 var RegularView = function (options) { // All of this code is common to both a `RegularView` and `SuperView` // being constructed. this.color = options && (options.color || 'Green'); // If execution arrives here from the construction of // a `SuperView`, `Backbone.View` will call `initialize` // that belongs to `SuperView`. This happens because here // `this` is `SuperView`, and `Backbone.View`, applied with // the current `this` calls `this.initialize.apply(this, arguments)` Backbone.View.apply(this, arguments) }; RegularView.extend = Backbone.View.extend; _.extend(RegularView.prototype, Backbone.View.prototype, { // Called if a `RegularView` is constructed`, // Not called if a `SuperView` is constructed. initialize: function () { console.log('RegularView initialized.'); }, say_hi: function() { console.log('Regular hi!'); } }); var SuperView = RegularView.extend({ // Called if a `SuperView` is constructed`, // Not called if a `RegularView` is constructed. initialize: function(options) { console.log('SuperView initialized.') }, say_hi: function() { console.log('Super hi!'); } }) 

Para el conjunto de pruebas, tomé las últimas pruebas de vistas de GitHub y reemplacé las ocurrencias de Backbone.View con RegularView . Las pruebas luego usan RegularView y los resultados de RegularView.extend() para asegurarse de que ambos hagan lo que se supone que deben hacer.