Доступ к свойствам родительского представления магистрали - PullRequest
9 голосов
/ 13 февраля 2012

У меня есть базовое представление, которое вызывает вспомогательное представление:

  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' в подвиде?

Ответы [ 2 ]

10 голосов
/ 13 февраля 2012

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 будет действовать как "переменная класса" в языках OO, не основанных на прототипах.

Правильный способ сделать это - использовать переменную экземпляра для 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 голосов
/ 13 февраля 2012

Просто предположение, но не могли бы вы попробовать что-то подобное в 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() {
    }
  });
...