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监听扫码枪输入并禁止手动输入的实现方法(推荐)
Mar 21 jQuery
jQuery实现一个简单的验证码功能
Jun 26 jQuery
详解webpack3如何正确引用并使用jQuery库
Aug 26 jQuery
基于jQuery实现Ajax验证用户名是否可用实例
Mar 25 jQuery
jQuery的Ajax接收java返回数据方法
Aug 11 jQuery
vue-cli 引入jQuery,Bootstrap,popper的方法
Sep 03 jQuery
jQuery插件实现非常实用的tab栏切换功能【案例】
Feb 18 jQuery
JQuery animate动画应用示例
May 14 jQuery
高效jQuery选择器的5个技巧实例分析
Nov 26 jQuery
jQuery实现简单弹幕效果
Nov 28 jQuery
jQuery实现全选、反选和不选功能的方法详解
Dec 04 jQuery
jQuery实现鼠标移入显示蒙版效果
Jan 11 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
PHP的cURL库简介及使用示例
2015/02/06 PHP
php简单统计字符串单词数量的方法
2015/06/19 PHP
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
js 数组实现一个类似ruby的迭代器
2009/10/27 Javascript
javascript实现动态模态绑定grid过程代码
2014/09/22 Javascript
JS基于递归算法实现1,2,3,4,5,6,7,8,9倒序放入数组中的方法
2017/01/03 Javascript
微信小程序实现实时圆形进度条的方法示例
2017/02/24 Javascript
bootstrap弹出层的多种触发方式
2017/05/10 Javascript
jQuery实现锚点向下平滑滚动特效示例
2017/08/29 jQuery
weebox弹出窗口不居中显示的解决方法
2017/11/27 Javascript
详解如何在vue项目中引入elementUI组件
2018/02/11 Javascript
webpack4 css打包压缩问题的解决
2018/05/18 Javascript
element ui table 增加筛选的方法示例
2018/11/02 Javascript
可能被忽略的一些JavaScript数组方法细节
2019/02/28 Javascript
vue cli3 配置proxy代理无效的解决
2019/10/30 Javascript
vue实现购物车选择功能
2020/01/10 Javascript
解决vue 使用setTimeout,离开当前路由setTimeout未销毁的问题
2020/07/21 Javascript
vue移动端写的拖拽功能示例代码
2020/09/09 Javascript
Python ORM框架SQLAlchemy学习笔记之关系映射实例
2014/06/10 Python
Python自动化部署工具Fabric的简单上手指南
2016/04/19 Python
python如何获取当前文件夹下所有文件名详解
2019/01/25 Python
python验证身份证信息实例代码
2019/05/06 Python
python TF-IDF算法实现文本关键词提取
2019/05/29 Python
python 数据生成excel导出(xlwt,wlsxwrite)代码实例
2019/08/23 Python
快速解决docker-py api版本不兼容的问题
2019/08/30 Python
CSS3中border-radius属性设定圆角的使用技巧
2016/05/10 HTML / CSS
香港个人化生活购物网站:Ballyhoo Limited
2016/09/10 全球购物
存储过程和sql语句的优缺点
2014/07/02 面试题
介绍一下write命令
2012/09/24 面试题
电子信息专业自荐书
2014/02/04 职场文书
请假条格式范文
2014/04/10 职场文书
食品安全处置方案
2014/06/14 职场文书
讲文明知礼仪演讲稿
2014/09/13 职场文书
工程部岗位职责范本
2015/04/11 职场文书
Python数组变形的几种实现方法
2022/05/30 Python
Ubuntu安装Mysql+启用远程连接的完整过程
2022/06/21 Servers