Jquery中.bind()、.live()、.delegate()和.on()之间的区别详解


Posted in jQuery onAugust 01, 2017

简介

最近了解到很多网页开发者对jquery中的 .bind() .live() .delegate() 和 .on() 方法存在很多的疑惑。这些疑惑通常是关于它们之间真正的区别是什么啊,什么时候该使用它们啊。下面本文将给大家详细介绍这四个方法之间的区别,分别对每个方法都进行了详细的介绍,话不多说,来一起看看详细的介绍:

在我们深入了解这些方法之前,我们先来一段常见的的HTML,作为我们编写jquery示例方法使用的样本。

<ul id="members" data-role="listview" data-filter="true">
 <!-- ... 其他li ... -->
 <li>
 <a href="detail.html?id=10" rel="external nofollow" >
  <h3>John Resig</h3>
  <p><strong>jQuery Core Lead</strong></p>
  <p>Boston, United States</p>
 </a>
 </li>
 <!-- ... 其他li ... -->
</ul>

使用Bind方法

.bind()方法将事件类型和一个事件处理函数直接注册到了被选中的DOM元素中。这个方法被使用得最久,在此期间,它很好的解决了各种跨浏览器的问题。当使用它来连接事件处理函数时,它仍然非常简洁,但是也存在着一些性能方面的问题,将在下面罗列出来。

/* .bind() 方法将事件类型和一个事件处理函数直接注册到了被选中的DOM元素中。 
 .click() 方法只是.bind() 方法的简写。
*/

$( "#members li a" ).bind( "click", function( e ) {} ); 
$( "#members li a" ).click( function( e ) {} );

.bind()方法将会把事件处理函数连接到所有匹配的a标签。这种方式并不好。这样做的话,它不仅在所有匹配的元素中隐含地迭代附加事件处理函数,而且这些操作非常浪费(多余),因为这些相同的事件处理函数是被一遍一遍的重复的添加到所有匹配的标签上。

优点:

  • 适用于各种浏览器
  • 连接事件处理函数非常方便快捷
  • 可以使用 .click() ,  .hover()等简写方法来更方面地连接事件处理函数
  • 对于一个简单的ID选择器,使用.bind() 方法不仅可以很快地连接事件处理函数,而且当事件被触发时, 事件处理函数几乎是马上就被调用了

缺点:

  • 这样方法会将所有的事件处理函数附加到所有匹配的元素
  • 不可以动态地匹配相同选择器的元素
  • 当操作大量匹配的元素时会有性能方面的问题
  • 附加操作是在前期完成的,这可能导致页面加载时存在性能问题

使用Live方法

.live()方法使用了事件委托的概念来实施其所谓的“魔法”。你调用live()方法的方式就像是调用bind()方法那样方便。然而在这表面之下, .live()方法与前者的实现方式大不相同。 .live()方法将与事件处理函数关联的选择器和事件信息一起附加到文档的根级元素(即document)。通过将事件信息注册到document上,这个事件处理函数将允许所有冒泡到document的事件调用它(例如委托型、传播型事件)。一旦有一个事件冒泡到document元素上,Jquery会根据选择器或者事件的元数据来决定哪一个事件处理函数应该被调用,如果这个事件处理函数存在的话。这个额外的工作将会在用户交互时对性能方面造成一定的影响,但是初始化注册事件的过程相当地快。

/* 方法将与事件处理函数关联的选择器和事件信息一起附加到文档的根级元素(即document) 
 ( "#members li a" & "click" ) */

$( "#members li a" ).live( "click", function( e ) {} );

.bind()这个例子与上面bind()方法的例子对比的话有一个优点在于它仅仅把事件处理函数附加到document元素一次,而不是很多次。这样不仅更快,而且还减少了性能的浪费。然而,使用这个方法也会带来很多问题,下面将一一列出。

优点:

  • 所有的事件处理函数都只会被注册一次,而不是像bind()那样进行多次注册
  • bind()方法升级到live()方法非常方便,你仅需要将"bind"替代为"live"就可以了
  • 那些被动态添加到DOM的元素也将被神奇的匹配到,因为真实的事件信息是被注册到document元素上的
  • 你可以在文档加载完之前连接事件处理函数,这样可以帮助你更好地利用你可能没有用的时间

缺点:

  • 这个方法在Jquery 1.7以后的版本被弃用了,你应该在你的代码里逐步放弃使用它
  • 使用这个方法时链式操作没有得到正确的支持,可能会出现某些错误
  • 所做的匹配操作基本上没用因为它只用于在document元素上注册事件处理函数
  • 使用 event.stopPropogation() 方法将会没用,因为事件总是已经被委托到了document元素上
  • 因为所有的选择器或者事件信息都被附加到document元素上了,所以一旦有一个事件要调用某个事件处理函数,Jquery会在一大堆储存的元数据中使用matchesSelector方法来决定哪一个事件处理函数将会被调用,如果这个函数有的话。
  • 因为你所连接的事件总是被委托到document上,所如果你的DOM的层级很深的话,这会导致一定的性能问题

使用Delegate方法

.delegate()方法与live()方式实现方式相类似,它不是将选择器或者事件信息附加到document,而是让你指定附加的元素。就像是live()方法一样,这个方法使用事件委托来正确地工作。

如果你跳过了前面关于 .live() 方法的介绍,你可能要回去重新看看它,因为这里涉及到之前我所阐述的一些内部逻辑

/* .delegate() 方法会将选择器和事件信息 ( "li a" & "click" ) 附加到你指定的元素上 ( "#members" )。
*/

$( "#members" ).delegate( "li a", "click", function( e ) {} );

.delegate()方法十分强大。在上面这个例子中,与事件处理函数关联的选择器和事件信息将会被附加到( #members" )这个元素上。这样做比使用live()高效多了,因为live()方法总是将与事件处理函数关联的选择器和事件信息附加到document元素上。另外,使用.delegate()方法解决许多其他问题。请参阅下方列出的详细信息。

优点:

  • 你可以选择将选择器或者事件信息附加到指定的元素。
  • 匹配操作实际上在前面并没有执行,而是用来注册到指定的元素。
  • 链式操作可以得到正确的支持
  • Jquery仍然需要迭代这些选择器或者事件信息来匹配元素,不过因为你可以选择哪一个元素作为根元素,所以筛选的量会大幅减少
  • 因为这项技术使用了事件委托机制,它可以匹配到被动态地添加到DOM的元素
  • 你可以在文档加载完之前连接事件处理函数

缺点:

  • .bind()方法不可以直接升级到.delegate()方法
  • Jquery仍然需要使用marchesSelector方法在附加到指定根元素的选择器或者事件信息中筛选决定哪一个事件处理函数会被调用。然而,附加到指定根元素的元数据会比使用live()方法的时候要小得多。
  • 当操作大量匹配的元素时会有性能方面的问题
  • 附加操作是在前期完成的,这可能导致页面加载时存在性能问题

使用On方法

你知道吗,在Jquery 1.7版本中.bind() .live() .delegate()方法只需要使用.on()方法一种方式来调用它们。当然.unbind() .die() 和.undelegate()方法也一样。一下代码片段是从Jquery 1.7版本的源码中截取出来的

bind: function( types, data, fn ) {
 return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
 return this.off( types, null, fn );
},

live: function( types, data, fn ) {
 jQuery( this.context ).on( types, this.selector, data, fn );
 return this;
},
die: function( types, fn ) {
 jQuery( this.context ).off( types, this.selector || "**", fn );
 return this;
},

delegate: function( selector, types, data, fn ) {
 return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
 return arguments.length == 1 ? 
  this.off( selector, "**" ) : 
  this.off( types, selector, fn );
}

考虑到这一点,使用.on()方法看起来像以下方式一样...

/* Jquery的 .bind() , .live() 和 .delegate() 方法只需要使用`.on()`方法一种方式来调用它们 */

// Bind
$( "#members li a" ).on( "click", function( e ) {} ); 
$( "#members li a" ).bind( "click", function( e ) {} );

// Live
$( document ).on( "click", "#members li a", function( e ) {} ); 
$( "#members li a" ).live( "click", function( e ) {} );

// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} ); 
$( "#members" ).delegate( "li a", "click", function( e ) {} );

你可能注意到了,我如何使用.on()方法决定了它如何调用其他方法。你可以认为.on()方法被具有不同签名的方法”重载“了,而这些方法实现了不同的事件绑定的连接方式。 .on()方法的出现为API带来了很多方面的一致性,并希望让事情变得不那么混乱。

优点:

  • 使各种事件绑定方法一致。
  • 因为在Jquery源码中.bind().live() .delegate()方法实际上是调用了此方法,因此简化了jQuery代码库并删除了一级重定向。
  • 这种方式仍然提供了使用.delegate()方法的优点,并且仍然提供对.bind()方法的支持,如果你需要的话。

缺点:

  • 给人带来了一些疑惑,因为方法的实际执行方式将根据你如何调用方法而改变。

总结

如果你对不同的绑定事件方法有所迷惑,那么不要担心,因为API发展了一段时间了,有很多前人的经验可以借鉴。也有很多人将这些方法视为魔法,不过一旦你了解了他们工作背后的原理,将帮助您了解如何更好地处理项目。
以下是这篇文章的精华所在...

  • 使用.bind()方法非常浪费性能因为它把同一个事件处理函数附加到了每一个匹配的元素上
  • 你应该停止使用.live()方法因为它被弃用了同时也会带来很多问题
  • 使用.delegate()方法会给你带来很多好处当你需要解决一些性能上的问题和对动态添加的元素作出处理
  • 新的.on()方法其实就是模拟.bind().live() .delegate()实现的语法糖,具体取决于你如何调用它
  • 新的方向是使用新的.on()方法。先熟悉语法,并开始在你的所有的Jquery 1.7版本以上的项目使用它吧!

对于上面列举的优点或者缺点,你有新的补充吗?你最近开始使用delegate()方法了吗?你对新的.on()方法怎么看呢?把你的想法写到用评论告诉我吧!谢谢!

第一次翻译,文章中可能会出现一些不通顺的地方,希望得到大家的理解,毕竟我还是个学生啊!

好了,大概就这样,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持

原文链接

jQuery 相关文章推荐
jQuery插件HighCharts绘制简单2D柱状图效果示例【附demo源码】
Mar 21 jQuery
jquery实现提示语淡入效果
May 05 jQuery
jQuery实现select下拉框获取当前选中文本、值、索引
May 08 jQuery
使用jquery+iframe做一个ajax上传效果(实例)
Aug 24 jQuery
jQuery菜单实例(全选,反选,取消)
Aug 28 jQuery
用jquery获取select标签中选中的option值及文本的示例
Jan 25 jQuery
jQuery实现表单动态添加数据并提交的方法
Jul 19 jQuery
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
Aug 28 jQuery
解决jQuery使用append添加的元素事件无效的问题
Aug 30 jQuery
利用jquery和BootStrap实现动态滚动条效果
Dec 03 jQuery
jquery实现的分页显示功能示例
Aug 23 jQuery
jquery实现点击弹出对话框
Feb 08 jQuery
jquery easyui如何实现格式化列
Jul 30 #jQuery
jQuery dateRangePicker插件使用方法详解
Jul 28 #jQuery
jQuery获取table表中的td标签(实例讲解)
Jul 28 #jQuery
vue单页应用中如何使用jquery的方法示例
Jul 27 #jQuery
jQuery实现键盘回车搜索功能
Jul 25 #jQuery
基于jquery实现多级菜单效果
Jul 25 #jQuery
jQuery实现拼图小游戏(实例讲解)
Jul 24 #jQuery
You might like
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
ThinkPHP模板输出display用法分析
2014/11/26 PHP
Smarty使用自定义资源的方法
2015/08/08 PHP
分享3个php获取日历的函数
2015/09/25 PHP
PHP读取并输出XML文件数据的简单实现方法
2017/12/22 PHP
PHP pthreads v3下的Volatile简介与使用方法示例
2020/02/21 PHP
Array.prototype.slice 使用扩展
2010/06/09 Javascript
基于jquery点击自以外任意处,关闭自身的代码
2012/02/10 Javascript
DWR实现模拟Google搜索效果实现原理及代码
2013/01/30 Javascript
js+html5实现可在手机上玩的拼图游戏
2015/07/17 Javascript
js基于面向对象实现网页TAB选项卡菜单效果代码
2015/09/09 Javascript
require.js配合插件text.js实现最简单的单页应用程序
2016/07/12 Javascript
微信小程序  自定义创建详细介绍
2016/10/27 Javascript
深入理解Angularjs中的$resource服务
2016/12/31 Javascript
jQuery使用eraser.js插件实现擦除、刮刮卡效果的方法【附eraser.js下载】
2017/04/28 jQuery
Vue.js学习教程之列表渲染详解
2017/05/17 Javascript
Angular 表单控件示例代码
2017/06/26 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【矩形情况】
2018/12/13 Javascript
js实现简单的轮播图效果
2020/12/13 Javascript
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
Python深入学习之装饰器
2014/08/31 Python
Python 遍历子文件和所有子文件夹的代码实例
2016/12/21 Python
pandas 小数位数 精度的处理方法
2018/06/09 Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
2018/11/29 Python
Python实现的特征提取操作示例
2018/12/03 Python
Python下简易的单例模式详解
2019/04/08 Python
使用Python控制摄像头拍照并发邮件
2019/04/23 Python
Python爬取爱奇艺电影信息代码实例
2019/11/26 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
2020/03/07 Python
python 一维二维插值实例
2020/04/22 Python
Python如何把十进制数转换成ip地址
2020/05/25 Python
Pycharm Git 设置方法
2020/09/15 Python
快速创建 HTML5 Canvas 电信网络拓扑图的示例代码
2018/03/21 HTML / CSS
员工工作表现评语
2014/04/26 职场文书
优秀教师先进材料
2014/12/16 职场文书
Python中rapidjson参数校验实现
2021/07/25 Python