2011-12-22 116 views
17

我们都知道做这样的事情是不好的:事件委托给子视图Backbone.js的

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

然后......

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

我一直在寻找通过大量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; 
    } 
}); 

列表项的看法:

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

如果我没有记错,实例化的ListView与500款集合,给了我500个点击事件,每行一个。这是不好的权利?

我知道骨干已建成事件代表团命名空间的事件:

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

我想我可以把这个在我的ListView,它只会造成整个列表点击事件,但后来我不会无法访问与点击的列表项目对应的模型数据。

骨干开发人员用什么模式解决这个典型问题?

回答

2

你可以像这样的元素的实例相关联:

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

然后:

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

感谢您的回复。这是我到目前为止解决这个问题所必须做的,但是再一次,它使用jQuery将数据存储在DOM中,从长远来看,感觉不像是一个非常干净的方法。 – Daniel 2011-12-22 12:22:28

+1

@Daniel jQuery不会将数据存储在DOM中,它会将其存储在常规js对象('jQuery.cache')中。 jQuery还内部污染了具有expando属性的事件的任何元素,然后在元素上执行'data'除了在常规js对象中添加更多属性之外没有任何效果。 – Esailija 2011-12-22 12:24:56

+0

啊好的。那么我想那样会有点工作。谢谢 – Daniel 2011-12-22 12:28:06

3

跟踪父视图的子视图。然后,当添加子视图时,将其添加到散列中,并将该cid添加到子视图的el中。这种方式有一个指向子视图,并可以在其模型等执行操作...

我还没有测试下面这个确切的代码,所以这可能是错误的地方或两个,但我已经测试了这个一般原则。我也省略了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; 
    } 
});