2012-02-13 13 views
9

Tengo una visión columna vertebral que llama a un sub-vista:Acceso a Propiedades de la espina dorsal de Padres Ver

lr.MapView = Backbone.View.extend({ 
    el: $('#map'), 
    foo: "bar", 
    initialize: function() { 
     var that = this; 
     _.bindAll(this, "render", "addAllEvents", "addOneEvent"); 
     this.collection = new lr.Events(); 
     this.collection.fetch({ 
     success: function(resp) { 
      that.render(); 
      that.addAllEvents(); 
     } 
     }); 
    }, 

    addAllEvents: function() { 
     this.collection.each(this.addOneEvent); 
    }, 

    addOneEvent: function(e) { 
     var ev = new lr.EventView({ 
     model: e 
     }); 
    }, 

    render: function() { 
    } 
    }); 

Aquí está la sub-vista:

lr.EventView = Backbone.View.extend({ 
    initialize: function() { 
     _.bindAll(this, "render"); 
     console.log(lr.MapView.foo); // will console.log 'undefined' 
    }, 
    render: function() { 
    } 
    }); 

me gustaría poder para acceder a las propiedades de la vista principal dentro de la subvista, pero no funciona con el código anterior. Por ejemplo, ¿cómo puedo acceder a la variable 'foo' dentro de la subvista?

Respuesta

10

lr.MapView es una "clase", todo lo que Backbone.View.extend construye estará en lr.MapView.prototype, no en lr.MapView. Ejecutar este con la consola abierta y verá que hay de nuevo:

var MapView = Backbone.View.extend({ foo: 'bar' }); 
console.log(MapView); 
console.log(MapView.prototype); 
console.log(MapView.prototype.foo); 

Demostración: http://jsfiddle.net/ambiguous/DnvR5/

Si sólo va a tener un solo MapView continuación, se puede hacer referencia a lr.MapView.prototype.foo todas partes:

initialize: function() { 
    _.bindAll(this, "render"); 
    console.log(lr.MapView.prototype.foo); 
} 

Tenga en cuenta que en todas partes incluye dentro de lr.MapView casos por lo que su foo actuará como una "variable de clase" de lenguajes orientados a objetos no basado en los prototipos.

La forma correcta de hacer esto es utilizar una variable de instancia para foo y pasar la instancia de vista de los padres a las instancias sub-vista cuando se crean a:

// In MapView 
addOneEvent: function(e) { 
    var ev = new lr.EventView({ 
    model: e, 
    parent: this 
    }); 
} 

// In EventView 
initialize: function(options) { 
    _.bindAll(this, "render"); 
    this.parent = options.parent; // Or use this.options.parent everywhere. 
    console.log(this.parent.foo); 
} 

O mejor, añadir un método de acceso a MapView:

_foo: 'bar', 
foo: function() { return this._foo } 

y usar ese método en el EventView:

initialize: function(options) { 
    // ... 
    console.log(this.parent.foo()); 
} 

La encapsulación y las interfaces adecuadas son una buena idea, incluso en JavaScript.

+0

Maravillosa respuesta, gracias. ¿Por qué el método de acceso es preferible a la otra alternativa que mencionas? – AdamVickers

+2

@ AdamVickers: La presencia de un descriptor de acceso indica al mundo exterior que 'foo()' es parte de la interfaz pública de MapView y la falta de un mutador indica que no se supone que los extraños lo cambien. –

0

Sólo una conjetura, pero ¿podría intentar algo como esto en MapView:

addOneEvent: function(e) { 
    var that = this, 
     ev = new lr.EventView({ 
      model: e, 
      parentView = that 
     }); 
} 

Y luego acceder a ella de esta manera:

lr.EventView = Backbone.View.extend({ 
    initialize: function() { 
     _.bindAll(this, "render"); 
     console.log(this.parentView.foo); 
    }, 
    render: function() { 
    } 
    }); 
Cuestiones relacionadas