2012-02-13 15 views
9

Mam widoku szkieletową, która wzywa do sub-widzenia:uzyskiwania dostępu do właściwości szkieletu Parent View

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() { 
    } 
    }); 

Oto sub-view:

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

Chciałbym móc aby uzyskać dostęp do właściwości widoku rodzica w podglądzie, ale nie działa z powyższym kodem. Na przykład, w jaki sposób mogę uzyskać dostęp do zmiennej "foo" w podglądzie?

Odpowiedz

10

lr.MapView jest "klasa", wszystko, co Backbone.View.extend buduje będzie w lr.MapView.prototype, a nie w lr.MapView. Uruchomić to z konsoli otwarte, a zobaczysz, co się dzieje:

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

Demo: http://jsfiddle.net/ambiguous/DnvR5/

Jeśli tylko będziemy mieć jeden MapView wtedy można odwołać się do lr.MapView.prototype.foo wszędzie:

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

Zauważ, że wszędzie zawiera wewnątrz lr.MapView przypadkach więc foo będzie działać jak „klasy zmiennej” z non-prototyp oparty językach oo.

Prawo sposobem na to jest użycie zmiennej instancji dla foo i przekazać instancję Zobacz główne do sub-view przypadkach gdy są one tworzone:

// 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); 
} 

Albo lepiej, dodać metody dostępowej do MapView:

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

i wykorzystać tę metodę w EventView:

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

Właściwa enkapsulacja i interfejsy to dobry pomysł nawet w JavaScript.

+0

Wspaniała odpowiedź, dziękuję. Dlaczego metoda metody dostępowej jest lepsza niż inna alternatywa, o której wspomniałeś? – AdamVickers

+2

@AdamVickers: Obecność accessora sygnalizuje światu zewnętrznemu, że 'foo()' jest częścią publicznego interfejsu MapView, a brak mutatora wskazuje, że osoby postronne nie powinny go zmieniać. –

0

tylko przypuszczenie, ale można spróbować czegoś takiego w MapView:

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

A następnie uzyskać dostęp to tak:

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