最近在AngularJS的开发中,遇到一个神奇的事情:我们用到livebox来预览评论列表中的图片, 然而评论列表是由Angular Resource动态载入的。不可思议的是,点击这些动态载入的图片仍然会触发lightbox的图片预览。 难道lightbox使用先进的MutationObserver技术监听了DOM的变化?观察lightbox源码才发现,原来只是jQuery的.on()方法:

  1. $('body').on('click', 'a[rel^=lightbox], ...', function(event){});

本文便来详解各种jQuery事件绑定方法:onbinddelegateliveunbindtrigger。 同时总结一下常用的jQuery事件技术:如何阻止事件冒泡、阻止浏览器默认行为、解绑事件处理函数、自定义事件。

什么是 jQuery 事件

jQuery事件是DOM事件的封装,同时支持自定义的扩展。在程序设计中,事件和代理有着相似的作用: 它们提供了一种机制,使得行为的实现方式和调用时机可以分离。

不谈jQuery,DOM本身就提供了一系列的javascript事件,例如clickkeyupsubmit。 未实现相关业务逻辑,通常会为这些事件定义一系列的处理函数,处理函数定义了业务的实现方式,而浏览器知道这些业务的调用时机。 Javascript事件就是这样一种机制,使得行为的实现方式和调用时机可以动态地绑定。

jQuery事件是通过封装javascript事件来实现的,例如.keyup()便是onkeyup的封装:

.keyup(): Bind an event handler to the “keyup” JavaScript event, or trigger that event on an element.

除了封装大多数的javascript事件,jQuery提供了统一的事件绑定和触发机制:

  • 绑定事件:bindonlivedelegatekeyup(<function>)
  • 触发事件:trigger('keyup')keyup()
  • 解绑事件:unbindoffdieundelegate

事件绑定:bind

使用javascript绑定一个事件很简单,只需要在HTML中设置onxxx属性, 并且在javascript中定义相关的处理函数便可以完成。

  1. <div onclick="func()"></div>
  2. <script>
  3. function func(){
  4. console.log('clicked!');
  5. }
  6. </script>

上述是基本的javascript事件处理方式,而jQuery提供了更加方便的方式:.bind()函数。

.bind():Attach a handler to an event for the elements.

  1. <div id='foo'></div>
  2. <script>
  3. $('#foo').click(function(){
  4. console.log('clicked!');
  5. });
  6. </script>

.click(<function>)等效于.bind('click', <function>)。另外还可以通过unbind来解绑事件:

  1. $('#foo').unbind('click');

如果unbind参数为空,则解绑匹配元素的所有事件处理函数。 在我的理解中,我们还是不要offunbinddie吧。即使不谈效率,它们也使得软件更难理解了。 如果你感觉有需要,下面的.on()应该会满足你~

.bind将会给所有匹配的元素都绑定一次事件,当元素很多时性能会变差。 而且后来动态新增的元素不会被绑定。

事件冒泡与默认行为

在DOM中默认情况下,事件是会冒泡的,即同样的事件会沿着DOM树逐级触发。 有时这是我们不希望的行为,可以在事件处理函数中阻止它。

  1. // 事件处理函数的第一个参数是一个事件对象
  2. $('#foo').click(function(event){
  3. event.stopPropagation();
  4. // do sth.
  5. });

浏览器对用户事件的默认行为是另一个需要考虑的事情,尤其是<a>标签的click事件。 当用户点击<a>标签时,首先调用所有的事件处理函数,然后执行默认行为:页面跳转或者定位。 同样地,我们可以阻止它:

  1. $('a').click(function(event){
  2. event.preventDefault();
  3. // do sth.
  4. });

在实践中,我们常常让事件处理函数return false来阻止冒泡和默认行为, 可以认为return false做了三件事情:

  1. stopPropagation()
  2. preventDefault()
  3. 立即结束当前函数并返回。
  1. $('a').click(function(event){
  2. // do sth.
  3. return false;
  4. });

自定义事件

jQuery事件是基于DOM事件的,但jQuery提供了更加普遍的事件机制。 这使得我们可以方便地自定义事件,只需要给一个尚不存在的事件名即可:

  1. <div id='foo'></div>
  2. <script>
  3. $('#foo').bind('fucked', function(){
  4. console.log("I'm fucked.");
  5. });
  6. $('#foo').trigger('fucked');
  7. </script>

这里定义了一个叫fucked的事件并绑定了处理函数,然后使用trigger来触发该事件。 在真实的场景中,通常用其他的事件来触发自定义事件:

  1. var he = 'man';
  2. $('#foo').click(function(){
  3. if(he === 'man') $(this).trigger('fucked');
  4. });

Delegate

.delegate是另一种绑定事件的方式。它将事件处理函数绑定在指定的根元素上, 由于事件会冒泡,它用来处理指定的子元素上的事件。

.delegate():Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.

  1. <div id="root">
  2. <a>Alice</a>
  3. <a>Bob</a>
  4. </div>
  5. <script>
  6. $('#root').delegate('a', 'click', function(){
  7. console.log('clicked');
  8. });
  9. </script>

它的使用方式比bind稍显复杂,但它的功能非常强大:

  1. 自动绑定动态添加的元素。因为事件处理函数绑定在#root上,新加的子元素事件也会冒泡到#root
  2. 性能好于.bind()。只绑定一个事件处理函数,绑定速度相当快。

如果你在使用AngularJS等动态操作DOM的工具,那么.delegate()将会非常实用,它能对新增的DOM元素自动绑定。

On

事实上,.on()才是jQuery事件的提供者。其他的事件绑定方法都是通过.on()来实现的,请看jQuery1.8.2的源码:

  1. bind: function( types, data, fn ) {
  2. return this.on( types, null, data, fn );
  3. },
  4. unbind: function( types, fn ) {
  5. return this.off( types, null, fn );
  6. },
  7. live: function( types, data, fn ) {
  8. jQuery( this.context ).on( types, this.selector, data, fn );
  9. return this;
  10. },
  11. die: function( types, fn ) {
  12. jQuery( this.context ).off( types, this.selector || "**", fn );
  13. return this;
  14. },
  15. delegate: function( selector, types, data, fn ) {
  16. return this.on( types, selector, data, fn );
  17. },
  18. undelegate: function( selector, types, fn ) {
  19. return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
  20. },

既然.on是最通用的jQuery事件机制,那么上述的所有例子都可以用.on()来实现:

  1. // bind
  2. $( "#foo" ).bind( "click", function( e ) {} );
  3. $( "#foo" ).on( "click", function( e ) {} );
  4. // delegate
  5. $( "#root" ).delegate( "a", "click", function( e ) {} );
  6. $( "#root" ).on( "click", "a", function( e ) {} );

我们看到上面还有一个.live()方法,它与delegate是类似的, 不过它强制指定了rootdocument(即this.context),因而性能略差。 自jQuery1.7起已经不推荐使用了。参见: https://api.jquery.com/category/deprecated/deprecated-1.7/

jQuery事件:bind、delegate、on的区别的更多相关文章

  1. Jquery中bind和live的区别

    Jquery中绑定事件有三种方法:以click事件为例 (1)target.click(function(){}); (2)target.bind("click",function ...

  2. jQuery 事件 - bind() 方法

    定义和用法 bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数. 实例1(一个事件) 记得把js引用地址换掉 当点击鼠标时,隐藏或显示 p 元素: <html&g ...

  3. jquery中bind和on的区别

    1.首先,来看看bind和on的语法. bind的用法: $('a').bind('click',[data],function(){}) 其事件的绑定者是固定的,就是a,第一个参数是事件,第二个参数 ...

  4. jQuery的.bind()、.live()和.delegate()的区别

    参考:http://kb.cnblogs.com/page/94469/ 摘要:jQuery的.bind()..live()和.delegate()之间的区别并非总是那么明显的,然而,如果我们对所有的 ...

  5. jQuery的.bind()、.live()和.delegate()之间区别

    摘要:jQuery的.bind()..live()和.delegate()之间的区别并非总是那么明显的,然而,如果我们对所有的不同之处都有清晰的理解的话,那么这将会有助于我们编写出更加简洁的代码,以及 ...

  6. jQuery的.bind()、.live()和.delegate(),on之间区别

    基本要素 51CTO推荐专题:jQuery从入门到精通 DOM树 首先,可视化一个HMTL文档的DOM树是很有帮助的.一个简单的HTML页面看起来就像是这个样子: 事件冒泡(又称事件传播) 当我们点击 ...

  7. Jquery中bind和live.one,delegate的区别

    Jquery中绑定事件有三种方法:以click事件为例 (1)target.click(function(){}); (2)target.bind("click",function ...

  8. jQuery事件绑定—on()、bind()与delegate()

    啃了一段日子的js相关了,学的过程中发现在jQuery中绑定事件时,有人用bind(),有人用on(),有人用delegate(),还有人用live(),看代码的时候觉得都实现功能了也就掀过去了,只是 ...

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

    简介 最近了解到很多网页开发者对jquery中的 .bind() .live() .delegate() 和 .on() 方法存在很多的疑惑.这些疑惑通常是关于它们之间真正的区别是什么啊,什么时候该使 ...

随机推荐

  1. 开始整理iOS职位面试问题及答案

    Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接 ...

  2. unix简史及应用

    Unix 简史 1965年时,贝尔实验室(Bell Labs)加入一项由奇异电子(General Electric)和麻省理工学院(MIT)合作的计画:该计画要建立一套多使用者.多任务.多层次(mul ...

  3. .NET:在C#中模拟Javascript的setTimeout方法

    背景 每种语言都有自己的定时器(Timer),很多人熟悉Javascript中的setInterval和setTimeout,在Javascript中为了实现平滑的动画一般采用setTimeout模拟 ...

  4. thinkphp输出表格

    //这是打印5列n行的表格,所以mod="5" value="4" <tr> <volist name="data" id ...

  5. JavaScript 中 Object ,Prototype 相关的属性和方法

    span { font-family: 'Consolas'; font-size: 10pt; color: #ffffff; } .sc0 { } .sc2 { color: #c0c0c0; } ...

  6. datagridview 纵向 横向 合并单元格

    datagridview 单元格合并:纵向以及横向合并参考了csdn上不知哪位的代码,具体哪位找不到连接了. 纵向合并: /// <summary> /// 纵向合并,即合并数据项的值 / ...

  7. linux CentOS7 修改系统时间

    linux在安装的时候如果时区选择错误,可以在系统安装完成之后修改.系统时间运行着也会有偏差,需要对时间进行实时同步,方法如下: 打开terminal 首先转到root权限 :并输入密码 然后输入:t ...

  8. 使用Nodejs的Nodemailer通过163信箱发送邮件例程

    首先需要安装一下nodemailer #nmp nodemailer install --save 然后就参照官方文档的例程改写一下就行了,代码如下: 'use strict'; const node ...

  9. Linux shell 提取文件名和目录名

    ${}用于字符串的读取,提取和替换功能,可以使用${} 提取字符串 1.提取文件名 [root@localhost log]# var=/dir1/dir2/file.txt [root@localh ...

  10. 工具篇:如何使用junit.jar进行测试

    一.网上下载:junit.jar包 下载地址:https://sourceforge.net/projects/junit/?source=typ_redirect 二.导入指定项目中 三.在指定方法 ...