2012-02-13 2 views
9

У меня есть вид магистральную, которая вызывает к югу зрения:Доступ Свойства Родитель Backbone 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() { 
    } 
    }); 

Вот суб-вид:

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

Я хотел бы быть в состоянии для доступа к свойствам родительского представления в подзадаче, но он не работает с указанным выше кодом. Например, как я могу получить доступ к переменной «foo» в подзадаче?

ответ

10

lr.MapView является "класс", все, что Backbone.View.extend строит будет в lr.MapView.prototype, а не в lr.MapView. Запустить с консолью открытым, и вы увидите, что происходит:

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

Демо: http://jsfiddle.net/ambiguous/DnvR5/

Если вы только собираетесь иметь один MapView, то вы можете обратиться к lr.MapView.prototype.foo везде:

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

Обратите внимание, что везде включает в lr.MapView случаях, чтобы ваш foo будет действовать как «класс переменный» из не-прототипа на основе объектно-ориентированных языков.

Правильный способ сделать это, чтобы использовать переменную экземпляра для foo и передать экземпляр родительского вида в случаях суб ракурса, когда они создаются:

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

Или лучше, добавьте акцесора чтобы MapView:

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

и использовать этот метод в EventView:

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

Правильная инкапсуляция и интерфейсы - хорошая идея даже в JavaScript.

+0

Замечательный ответ, спасибо. Почему подход метода доступа предпочтительнее другой альтернативы, которую вы упоминаете? – AdamVickers

+2

@AdamVickers: наличие сигнала доступа к внешнему миру, что 'foo()' является частью открытого интерфейса MapView, а отсутствие мутатора указывает на то, что аутсайдеры не должны изменять его. –

0

Только предположение, но вы могли бы попробовать что-то подобное в MapView:

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

А затем получить доступ к нему, как это:

lr.EventView = Backbone.View.extend({ 
    initialize: function() { 
     _.bindAll(this, "render"); 
     console.log(this.parentView.foo); 
    }, 
    render: function() { 
    } 
    }); 
Смежные вопросы