对jQuery的事件绑定的一些思考(补充)


Posted in Javascript onApril 20, 2013

首先我们看下面的一个很常见的事件绑定代码:

//example 
$('#dom').click(function(e){ 
//do something 
}); $('#dom2').click(function(e){ 
//do something 
});

这段代码在事件绑定处理上有一些缺陷:

过多的事件绑定会损耗内存
后期生成HTML会没有事件绑定,需要重新绑定
语法过于繁杂

解决方案

对于1、2两点的解决方案,我们首先先了解一下jQuery的事件绑定

jQuery的事件绑定有多个方法可以调用,以click事件来举例:

click方法

bind方法
delegate方法
on方法

不管你用的是(click / bind / delegate)之中那个方法,最终都是jQuery底层都是调用on方法来完成最终的事件绑定。因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不如直接都采用on方法来的痛快和直接。

关于对方法的详细解释和用例,请直接访问jQuery官网,在这里不一一说明。api.jquery.com

性能

首先我们需要先对不同的事件绑定方式之间的内存占用差距有一个清晰的认识。

对于性能的分析将采用Chrome的Developer Tools。
Profiles --> Take Heap Snapshot,用这个工具我们可以看到Javascript所占用的内存,能够对性能问题进行分析。

对jQuery的事件绑定的一些思考(补充)

DEMO HTML
<html> 
<head> 
<script type="text/javascript"> 
$(function(){ 
$('#btn-add').click(function(){ 
$('.ul').prepend('<li><a href="javascript:;">text</a></li>'); 
}); 
}); 
</script> 
</head> 
<body> 
<button id="btn-add">Create Element</button> 
<ul class="ul"> 
<li><a href="javascript:;">text</a></li> 
<!-- 2000 line... --> 
<li><a href="javascript:;">text</a></li> 
</ul> 
</body> 
</html>

Method 1

$(function(){ 
$('.ul a').click(function(e){ 
alert('click event'); 
}); 
});

以下是Method 1的内存分析图

内存占用约3.4M

对jQuery的事件绑定的一些思考(补充)

Method 2
$(function(){ 
$('.ul').on('click', 'a', function(e){ 
alert('click event'); 
}); 
});

以下是Method 2的内存分析图

内存占用约2.0M

对jQuery的事件绑定的一些思考(补充)

结论
Method 1 明显比 Method 2 多耗1.4M的内存

Method 1 无法将事件绑定到通过点击button所新增DOM中来,而Method 2可以。
只要on的delegate对象是HTML页面原有的元素,由于是事件的触发是通过Javascript的事件冒泡机制来监测,所以对于所有子元素(包括后期通过JS生成的元素)所有的事件监测均能有效,且由于不用对多个元素进行事件绑定(在这个example中为2000+a标签),能够有效的节省内存的损耗。

思考
代码如诗,但很容易变成代码如屎。如何提高代码的优雅程度也是一个很有意思的事情。

以下是一个很普通且普遍的JS文件的代码片段(用于一般网站)

$('#btn-add').click(function(){ 
//do something 
}); 
$('.action-box #btn-delete').click(function(){ 
//do something 
}); 
$('.action-box #btn-sort').mouseenter(function(){ 
//do something 
}); 
/** 
**more same code 
*/

毫不夸张的说,当一个js文件上百行后,类似于上面的代码,你很难从里面发现规律。

1、可能A喜欢写#btn-add,而B喜欢写.action-box #btn-add来作为选择符。
2、堆砌着许多不同类型事件,没有一个次序可言
3、没有运用到我们刚刚所讲的利用事件冒泡来做事件绑定

对jQuery的事件绑定的一些思考(补充)

改进
我们来一步步改进一下之前的JS代码

Version 1

$('.action-box').on('click', '#btn-add', function(){
  //do something
});
$('.action-box').on('click', '#btn-delete', function(){
  //do something
});

虽然运用了事件冒泡,不过感觉还是有点累赘,.action-box出现多次,感觉不舒服,让我们继续改进

Version 2

$('.action-box').on('click', '#btn-add, #btn-delete', function(){
  if($(this).attr('id') == 'btn-add'){
    //do something
  } else{
    //do something
  }
});

感觉比刚刚好多了,不过还是需要判断元素来做出相应的处理,能接受,但不完美。

灵感

首先看一下css的增强版本sass对于css语法上面的改进

/*bed css code*/
.action-box { width: 100%; color: #000; }
#btn-add { color: blue; }
#btn-delete { color: red; }
/*good css code*/
.action-box { width: 100%; color: #000; }
  .action-box #btn-add { color: blue; }
  .action-box #btn-delete { color: red; }
/*sass code*/
.action-box {
  width: 100%;
  color: #000;
  #btn-add {
    color: blue;
  }
  #btn-delete {
    color: red;
  }
}

我们可以在 good css code 和 sass code 从中可以可以很清晰了然的看到文档结构:.action-box 下面有两个button。

这是否能让sass这种代码结构运用到js中来呢?答案当然是可以。

$('.action-box').coffee({
  click: {
    '#btn-add': function(){
      //do something
    },
    //这是是支持jQuery的':last / [attr] / :eq(0)'等方法的 
    '#btn-delete': function(){
      //do something
    }
  },
  mouseenter: {
    '#btn-sort': function(){
      //do something
    }
  }
});

喜欢这种结构吗?

1、清晰明了的文档结构
2、运用事件冒泡,有效减少内存的占用
3、第一级别用事件名称来划分
4、第二级别的属性名相当于选择符。

coffee函数的源码

$.fn.coffee = function(obj){
  for(var eName in obj)
    for(var selector in obj[eName])
      $(this).on(eName, selector, obj[eName][selector]);
}

聊聊数行代码,就可以做成一个很美妙的语法糖

Enjoy yourself !  ^_^

作者: CoffeeDeveloper

Javascript 相关文章推荐
解读JavaScript中 For, While与递归的用法
May 07 Javascript
深入浅析JavaScript中with语句的理解
May 12 Javascript
深入理解jQuery之防止冒泡事件
May 24 Javascript
Dojo获取下拉框的文本和值实例代码
May 27 Javascript
jQuery实现的placeholder效果完整实例
Aug 02 Javascript
值得分享的JavaScript实现图片轮播组件
Nov 21 Javascript
基于Vue2-Calendar改进的日历组件(含中文使用说明)
Apr 14 Javascript
mpvue微信小程序开发之实现一个弹幕评论
Nov 24 Javascript
JavaScript canvas动画实现时钟效果
Feb 10 Javascript
详解JavaScript中的Object.is()与&quot;===&quot;运算符总结
Jun 17 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
Jul 26 Javascript
原生JS实现pc端轮播图效果
Dec 21 Javascript
A标签中通过href和onclick传递的this对象实现思路
Apr 19 #Javascript
javascript中onclick(this)用法介绍
Apr 19 #Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
Apr 19 #Javascript
使用jQuery同时控制四张图片的伸缩实现代码
Apr 19 #Javascript
使用jQuery实现的网页版的个人简历(可换肤)
Apr 19 #Javascript
兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码
Apr 19 #Javascript
JS实现div内部的文字或图片自动循环滚动代码
Apr 19 #Javascript
You might like
PHP脚本中include文件出错解决方法
2008/11/20 PHP
php自定义类fsocket模拟post或get请求的方法
2015/07/31 PHP
Javascript中的isNaN函数使用说明
2011/11/10 Javascript
JavaScript实现的GBK、UTF8字符串实际长度计算函数
2014/08/27 Javascript
jQuery插件imgPreviewQs实现上传图片预览
2016/01/15 Javascript
终于实现了!精彩的jquery弹幕效果
2016/07/18 Javascript
工作中比较实用的JavaScript验证和数据处理的干货(经典)
2016/08/03 Javascript
jquery获取input type=text中的值的各种方式(总结)
2016/12/02 Javascript
JS制作类似选项卡切换的年历
2016/12/03 Javascript
js实现类bootstrap模态框动画
2017/02/07 Javascript
jquery PrintArea 实现票据的套打功能(代码)
2017/03/17 Javascript
ECMAscript 变量作用域总结概括
2017/08/18 Javascript
小程序图片剪裁加旋转的示例代码
2018/07/10 Javascript
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
vue 之 css module的使用方法
2018/12/04 Javascript
Vue.js特性Scoped Slots的浅析
2019/02/20 Javascript
浅谈vue权限管理实现及流程
2020/04/23 Javascript
微信小程序弹窗禁止页面滚动的实现代码
2020/12/30 Javascript
[07:43]《辉夜杯》公开赛晋级外卡赛战队—TRG训练生活探秘
2015/12/11 DOTA
python写的一个文本编辑器
2014/01/23 Python
python实现对csv文件的列的内容读取
2018/07/04 Python
Python UnboundLocalError和NameError错误根源案例解析
2018/10/31 Python
[原创]Python入门教程4. 元组基本操作
2018/10/31 Python
Selenium python时间控件输入问题解决方案
2020/07/22 Python
Python logging自定义字段输出及打印颜色
2020/11/30 Python
澳大利亚第一的设计师礼服租赁网站:GlamCorner
2017/08/13 全球购物
什么是用户模式(User Mode)与内核模式(Kernel Mode) ?
2014/07/21 面试题
酒店人事专员岗位职责
2013/12/19 职场文书
美发店5.1活动方案
2014/01/24 职场文书
有创意的广告词
2014/03/18 职场文书
分公司任命书
2014/06/06 职场文书
奉献家乡演讲稿
2014/09/16 职场文书
租车协议书
2015/01/27 职场文书
社区党支部承诺书
2015/04/29 职场文书
2016春季小学开学寄语
2015/12/03 职场文书
教你一步步实现一个简易promise
2021/11/02 Javascript