【问题标题】:Accessing Properties of Parent Backbone View访问父主干视图的属性
【发布时间】:2012-03-04 12:16:13
【问题描述】:

我有一个调用子视图的主干视图:

  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”变量?

【问题讨论】:

    标签: backbone.js javascript javascript-framework


    【解决方案1】:

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

    请注意,everywhere 包含在 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 中,适当的封装和接口也是一个好主意。

    【讨论】:

    • 精彩的回答,谢谢。为什么访问器方法比您提到的其他替代方法更可取?
    • @AdamVickers:访问器的存在向外界表明 foo() 是 MapView 的公共接口的一部分,而缺少 mutator 则表明外界不应该更改它。跨度>
    【解决方案2】:

    只是一个猜测,但你能在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() {
        }
      });
    

    【讨论】:

      猜你喜欢
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多