简体   繁体   English

将事件委托给Backbone.js中的子视图

[英]Delegating events to sub-views in Backbone.js

We all know doing something like this is bad: 我们都知道做这样的事情很糟糕:

<ul>
  <li>Item</li>
  <li>Item</li>
  ... 500 more list items
</ul>

and then... 然后...

$("ul li").bind("click", function() { ... });

I've been looking through a lot of Backbone examples / guides and the following seems to be a standard approach to rendering a list with items, based from a collection of models. 我一直在浏览很多Backbone示例/指南,以下似乎是基于模型集合呈现包含项目的列表的标准方法。

var ListView = Backbone.View.extend() {

  tagName: 'ul',

  render: function() {
    this.collection.each(function(item) {
      var view = new ListItemView({model: item});
      $(this.el).append(view.render().el);
    });
    return this;
  }
});

A list item view: 列表项视图:

var ListItemView = Backbone.View.extend() {

  tagName: 'li',

  events: {
   'click' : 'log'
  }

  log : function() {
    console.log(this.model.get("title"));
  }

  render: function() {
    $(this.el).html(this.template(this.model.toJSON()));
    return this;
  }
});

If I'm not mistaken, instantiating the listView with a collection with 500 models, gives me 500 click events, one for each row. 如果我没弄错,用500个模型的集合实例化listView,给我500个点击事件,每行一个。 This is bad right? 这不好吧?

I know Backbone has built in event delegation for namespaced events: 我知道Backbone内置了名称空间事件的事件委托:

events : {
  'click li' : 'log'
}

I suppose I could put this in my ListView, and it would only create one click event for the entire list, but then I wouldn't be able access to model data corresponding to the clicked list item. 我想我可以将它放在我的ListView中,它只会为整个列表创建一个单击事件,但之后我将无法访问与单击列表项对应的模型数据。

What patterns do backbone developers use to solve this typical problem? 骨干开发人员使用什么模式来解决这个典型问题?

Derick Bailey写了一篇关于这个困境的详细博客文章,你可以在这里查看: http//lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-元件/

Keep track of the subviews from the parent view. 从父视图跟踪子视图。 Then when adding the subview add it to the hash as well as add the cid to the el of the subview. 然后,在添加子视图时,将其添加到哈希以及将cid添加到子视图的el中。 This way have a pointer to the subview and could perform operations on its model etc... 这种方式有一个指向子视图的指针,可以对其模型等执行操作......

I have not tested this exact code below so THIS may be wrong in a place or two but I have tested this general principle. 我没有测试下面这个确切的代码所以这可能在一两个地方是错的,但我已经测试了这个一般原则。 I have also omitted the listitemview code. 我也省略了listitemview代码。

var ListView = Backbone.View.extend() {
  subViews: {},
  tagName: 'ul',
  events: {
    'click li' : 'clickItem'
  },
  clickItem: function(event){
     var id = event.currentTarget.cid;
     var subView = this.subViews[id];


  },
  render: function() {

    this.collection.each(function(item) {
      var view = new ListItemView({model: item});
      this.subViews[view.cid] = view;
      subEl = view.render().el;
      subEl.cid = view.cid;
      $(this.el).append(subEl);
    });
    return this;
  }
});

You can associate the instance with an element like so: 您可以将实例与如下元素关联:

events : {
  'click li' : 'log'
},

log: function( e ) {
var elm = e.currentTarget //Same as `this` in normally bound jQuery event


jQuery.data( elm, "viewInstance" ).log( e );
},

Then: 然后:

var ListItemView = Backbone.View.extend() {

  tagName: 'li',

  log : function() {
    console.log(this.model.get("title");
  }

  render: function() {
        //Associate the element with the instance
    $(this.el).html(this.template(this.model.toJSON())).data( "viewInstance", this );
    return this;
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM