Backbone.js中events中事件不生效

来源:互联网 发布:极乐净土镜头数据 编辑:程序博客网 时间:2024/05/29 13:37

使用 Backbone 的 View 时,可以象传统 jQuery 那样定义事件,$("selector").click(function(){...})。幸运的是 Backbone 让我们在 View 中定义事件变得更为简单和集中,只要设置 View 的 events 属性,配置 事件,元素以及相应的处理方法,基本模式如下:

    events: {
        “click button”: “event_handler”,
        “focus #name”: “event_handler”
    },
    event_handler: function( event ){
        alert(event.target.id);
    }

格式是 "事件 选择器": "事件处理函数名"


假设 html 内容为:
Html代码  收藏代码
  1. <div id="container">  
  2. </div>  

而 template 内容为:
Html代码  收藏代码
  1. <script type='text/template' id='tpl'>  
  2.     <div class="myclass">  
  3.         事例内容  
  4.     </div>  
  5. </script>  
在view视图中如下设置之后:
Javascript代码  收藏代码
  1. window.appView = Backbone.View.extend({  
  2.     template: _.template(jQuery("tpl").html()),  
  3.     events: {  
  4.         "click div""onClick",  
  5.     },  
  6.     onClick: function (e) {  
  7.         alert(this);  
  8.     },  
  9.     initialize: function (pid) {  
  10.         this.parent = jQuery(jQuery("#"+pid)[0]);  
  11.         this.render();  
  12.     },  
  13.     render: function () {  
  14.         this.parent.html(""); // 先清空窗口内的其他内容  
  15.         this.parent.html(this.template());  
  16.     },  
  17. });  
鼠标单击却不能触发onClick函数。后来通过跟踪 jQuery.on() 函数的执行,发现在内部传进去的 this 参数里,this.el.outerHTML 的值是 "<div></div>",即为默认 tag。因为 Backbone 中的事件响应,是根据 this.el.outerHTML 里的元素来设置的,那么在分配事件响应函数的时候,this.el.outerHTML 里没有元素,就意味着事件响应函数的失败!

所以正确的写法应该是:

Javascript代码  收藏代码
  1. window.appView = Backbone.View.extend({  
  2.     template: _.template(jQuery("tpl").html()),  
  3.     events: {  
  4.         "click div""onClick",  
  5.     },  
  6.     onClick: function (e) {  
  7.         alert(this);  
  8.     },  
  9.     initialize: function (pid) {  
  10.         this.parent = jQuery(jQuery("#"+pid)[0]);  
  11.         this.render();  
  12.     },  
  13.     render: function () {  
  14.         this.$el.html(this.template()); // 将tpl中的内容写入到 this.el 元素中  
  15.         this.parent.html(""); // 先清空窗口内的其他内容  
  16.         this.parent.html(this.el);  
  17.         this.delegateEvents();      // 由于重绘了整个视图(this.$el.html(...);),所以保险的办法是重新绑定所有事件  
  18.         return this;        // 这里借鉴的是 Backbone 教程里 todo.js 的做法  
  19.     },  
  20. });  

这样一来,this.el 里的内容就不再是 "<div></div>" 了,而是 '<div> <div class="myclass"> 事例内容 </div></div>' 了。这时再时行事件响应函数的分配时,就能在 this.el 里面找到一个div,并为之分配一个 onClick 函数了。

同时,由于在 render() 的开头,用 this.$el.html(this.template()); 重新绘制了整个视图,所以保险办法是调用 this.delegateEvents(); 重新绑定所有事件。

这里有一个问题,就是为什么不把 this.el 设置为 jQuery("#container"); 呢?其实一开始我也是这样做的,这样做的话 click 事件就可以很方便地响应到了,因为render() 之后 this.el 里肯定不只是 "<div></div>" 的。但是这样做的话,在视图 remove() 的时候就会出问题了。remove() 的效果是把 this.el 整个节点删除,也就是说,“<div id="container"></div>” 也会被删除!那么后来如果还有元素想在这个容器中写入的话,就会出错了!因为网页中已经没有了 id="container" 这个容器了!大家可以多看看 Backbone 官网上的 Todo 例子,个人觉得相当经典!网址如下:http://backbonejs.org/examples/todos/index.html
0 0
原创粉丝点击