Backbone:从元素中获取视图对象

时间:2013-02-19 14:55:46

标签: backbone.js

假设我有一些项目要显示在列表中。该列表具有将所有项目聚合为项目视图的视图。现在我想处理项目视图上的点击事件,并将处理委托给列表视图。

让我们看一些示例代码:

ItemView = Backbone.View.extend({
    className: 'item',
    initialize: function() {
        this.$el.data('backbone-view', this);
    }
});

请注意,我将视图对象本身作为根元素的属性附加,这实际上为视图和元素创建了一个循环引用情形。

ListView = Backbone.View.extend({
    initialize: function() {
        // contains the item views
        this.items = [];

        // click event delegation
        this.$el.click(_.bind(this._onClick, this));
    },

    addItem: function(v) {
        if ( !(v instanceof ItemView) ) return;

        this.items.push(v);
        this.$el.append(v.el);
    },

    _onClick: function(e) {
        var el = $(e.target).closest('.item'),
            view = el.data('backbone-view');

        // do something with the view
    }
});

每当必须处理任何类型的列表视图时,这是一种非常通用的模式。

我通过我在初始化时间项目上设置的data属性在处理程序中获取项目视图。我需要获取项目视图,因为我想在项目上执行的任何操作都是基于视图的。

另请注意,我使用的是closest,因为项目视图可能很复杂,而click事件的实际目标可能是根元素的后代。

所以问题:这是通过data属性将视图绑定到它的根元素的正确方法 - 特别是在考虑垃圾收集和内存泄漏时?能有更好的东西吗?

1 个答案:

答案 0 :(得分:1)

您应该在子视图中捕获事件。在我看来,任何Backbone视图都应该只处理其元素及其子元素的DOM事件。如果视图是嵌套的,那么最具体的视图应该处理事件。

如果要将处理委托给父视图,可以在ItemView中触发骨干事件,并听取ListView中的那些事件。

ItemView = Backbone.View.extend({
  events: {
    "click":"onClick"
  },
  onClick: function() {
    //trigger a custom event, passing the view as first argument
    this.trigger('click', this);
  }
});

ListView = Backbone.View.extend({
  addItem: function(v) {
    if ( !(v instanceof ItemView) ) return;
    //listen to custom event
    this.listenTo(v, 'click', this._onClick);
    this.items.push(v);
    this.$el.append(v.el);
  },
  _onClick:function(itemView) {
    //...
  }
});

如果click事件代表某些“更高级别”操作,例如selectactivate,则应将自定义事件命名为此类。这样,您可以在视图之间创建一个逻辑的,健壮的接口,而不必将父ListView与其子项的实现细节相关联。只有ItemView才能知道它是否已被点击,悬停,双击等。