详解jQuery事件


Posted in Javascript onJanuary 13, 2017

事件是 Web 应用中不可或缺的一个东西,用户在应用中执行一个操作的时候,比如鼠标单击时要触发执行一些事情,就可以给该事件绑定一个事件处理程序(event handler)。使用 jQuery 的 .on() 方法可以为选中的元素绑定任意的 DOM 事件,并添加事件处理程序。假设有如下 HTML 结构:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="utf-8">
</head>
<body>
 <button id="example" type="button">Click me!</button>
 <script src="http://code.jquery.com/jquery-1.11.2.js"></script>
 <script>
 // code here
 </script>
</body>
</html>

在 <script> 元素内添加如下代码,其中,事件名称是 .on() 方法的第一个参数,事件处理程序的回调函数作为第二个参数:

$('#example').on('click', function(e) {
 alert('Clicked!');
});

这样当该按钮元素触发鼠标单击(click)事件的时候就会执行绑定的事件处理程序,弹出一个对话框!回调函数的第一个参数 e 为事件对象,通过该对象可以得到很多事件相关的信息,比如事件类型,事件发生的坐标点等以及一些事件方法。回调函数除了可以像这样使用一个匿名函数,也可以使用一个变量标识的函数引用:

$('#example').on('click', clickHandler);

同时绑定多个事件

另外,jQuery 还支持使用空格分隔多个事件名称来同时绑定多个事件,比如 mouseenter mouseleave,同时给元素绑定鼠标移入和鼠标移出事件。可以通过事件对象的 type 属性来判断发生的是哪个事件:

$('#example').on('mouseenter mouseleave', function(e) {
 if (e.type === 'mouseenter') {
 // mouseenter
 } else {
 // mouseleave
 }
});

除了上面这种方法外,还可以传入一个键值对来绑定多个事件:

$('#example').on({
 mouseleave: function() {
 // mouseleave
 },
 mouseenter: function() {
 // mouseenter
 }
});

事件上下文

同时给多个元素绑定事件处理程序的时候可以使用事件执行的上下文来简化代码:

$('li').on('click', function() {
 var $this = $(this);
 $this.addClass('active');
});

上下文关键字 this 引用的是原生 DOM 元素,所以如果要使用 jQuery 的方法需要先包装成 jQuery 对象。

事件委托

事件会经过一个捕捉和冒泡的过程,为了兼容,jQuery 只使用了事件的冒泡,即目标元素触发事件后会逐级冒泡直到顶级元素节点。利用事件的冒泡可以将目标元素的事件处理程序绑定到其祖先元素上统一处理,可以给 .on() 方法传入一个可选的选择器字符串作为第二个参数:

$(document).on('click', '#example', clickHandler);

此时表示将 id="example" 的元素的鼠标单击事件委托绑定到了 document 元素上,当目标元素(即 id="example" 的元素)触发鼠标单击事件的时候,该事件就会冒泡到 document 元素上,从而触发事件处理程序。使用事件委托的好处是如果页面上有很多列表,每个列表都去绑定一个鼠标单击事件,那么就会有很多事件处理程序,会对性能造成影响。利用事件冒泡的原则,将事件处理程序绑定到目标元素的父元素或者祖先元素上,可以明显地减少事件处理程序的数量,改善性能:

$('ul').on('click', 'li', clickHandler);

使用事件委托另外一个好处是那些动态添加的 <li> 元素也会具有事件处理程序。个人比较侵向于将事件都委托到 document 元素上方便管理,而且也不用等到 DOM 准备就绪:

$(document)
 .on('click', 'selector-1', clickHandler)
 .on('focusin', 'selector-2', focusHandler);

在 IE8 中一些事件比如 submit 或者 change 是不会冒泡的,但是 jQuery 对此做了处理,因此也可以放心使用。像 focus 和 blur 事件则推荐使用相应的 focusin 和 focusout 事件来代替。对于 mouseover 和 mouseout 事件,为了避免事件冒泡造成的不良影响,推荐使用 mouseenter 和 mouseleave 来代替。

阻止事件冒泡与默认行为

调用事件对象的 .stopPropagation() 方法可以阻止事件冒泡:

$('#example').on('click', function(e) {
 e.stopPropagation();
});

这样当单击事件在该元素上发生的时候就不会冒泡了。jQuery 还有另外一个方法 .stopImmediatePropagation() 调用后事件冒泡被阻止同时该元素上后面绑定的事件处理程序也不会执行了:

$('#example').on('click', function() {
 alert('Clicked-1!'); // 会执行
}).on('click', function(e) {
 e.stopImmediatePropagation();
}).on('click', function() {
 alert('Clicked-2!'); // 不会执行
});

调用事件对象的 .preventDefault() 方法可以阻止事件的默认行为:

$('#example').on('click', function(e) {
 e.preventDefault();
});

在事件处理程序中直接返回 false 可以同时取消冒泡和阻止默认行为:

$('#example').on('click', function() {
 return false;
});

相当于同时调用了事件对象上面的 .stopPropagation() 和 .preventDefault() 方法。如果没有其它操作,还可以进一步简写为 $('#example').on('click', false);。

应用示例,点击按钮显示弹出层,点击文档其它地方隐藏:

$(document)
 .on('click', '#example', popup.show)
 .on('click', popup.hide);

由于事件冒泡,所以该弹出层并不会显示出来,需要在事件处理程序中阻止事件冒泡:

$(document)
 .on('click', '#example', function(e) {
 e.stopPropagation();
 popup.show();
 }).on('click', popup.hide);

获取原生事件对象

事件处理程序中引用的事件对象实际上是经过 jQuery 包装过的,有时候需要使用浏览器原生的事件对象,要得到浏览器原生的事件对象可以通过事件对象的 originalEvent 属性获取。例如,使用拖拽事件的时候就会用到原生的事件对象:

$('#example').on('dragstart', function(e) {
 var originalEvent = e.originalEvent;
 originalEvent.dataTransfer.effectAllowed = 'move';
 originalEvent.dataTransfer.setData('text/plain', $(this).text());
 originalEvent.dataTransfer.setData('text/html', $(this).html());
 originalEvent.dataTransfer.setDragImage('/images/drag.png', -10, -10);
});

传递数据

可以给事件处理程序传入数据,该数据保存在事件对象的 data 属性中:

$('#example').on('click', 1, function(e) {
 console.log(e.data); // 1
});

为了区别事件代理,传递的数据貌似不能是一个直接的字符串,不过可以传入一个对象来代替:

$('#example').on('click', {str: 'xxx'}, function(e) {
 console.log(e.data.str); // xxx
});

自定义事件

除了浏览器的标准事件,还可以绑定自定义事件的事件处理程序,其中事件名可以使用任意命名:

$('#example').on('sleep', function() {
 alert('Sleeping!');
});

标准事件的事件处理程序可以通过浏览器原生事件去触发,而自定义事件的事件处理程序则可以使用 jQuery 的 .trigger() 方法触发,使用方式如下,传入需要触发的事件名称作为参数:

$('#example').trigger('sleep');

可以通过给 trigger() 方法传入更多参数来给事件处理程序传递数据,数据会作为回调函数的参数进行传递:

$('#example').on('sleep', function(e, time) {
 alert('Sleep at' + time);
});
$('#example').trigger('sleep', '22:00');

应用示例,使用自定义事件编写异步代码:

$('#example').on('done', doHandler);
function foo() {
 setTimeout(function() {
 // foo 函数的逻辑比较耗时,所以使用 setTimeout 函数排队
 $('#example').trigger('done'); // 执行完了,通知一声
 }, 1000);
}

foo 函数执行完成后,就会触发元素的 done 事件,前面绑定的 doHandler 函数就会开始执行。

事件命名空间

无论是浏览器标准事件或是自定义事件都可以添加命名空间,添加在事件名称后面,通过一个 . 号分隔,像这样 click.widget,也可以给一个事件添加多个命名空间 click.widget.common,使用命名空间可以更有针对性地触发或者移除某个特定的事件处理程序。比如一个元素同时绑定了 click.tab 和 click.collapse 两个点击事件,当使用 .trigger() 方法触发 click.collapse 事件时会执行该事件的事件处理程序,而 click.tab 的事件处理程序则不会执行。

移除绑定事件

使用 .off() 方法可以移除绑定的事件处理程序,有下面几种情况:

  • 不指定任何参数,移除该元素上绑定的所有事件处理程序。
  • 指定事件名,如 .off('click') 表示移除该元素上绑定的所有单击事件处理程序。
  • 指定事件处理程序,如 .off('click', clickHandler) 表示仅移除该事件处理程序(是的,匿名函数不能这样移除)。
  • 指定事件命名空间,如 .off('.widget') 表示移除该命名空间下所有的事件处理程序(比如绑定的 click.widget 和 change.widget 事件处理程序都会被移除),该方式可以用于移除某个组件绑定的各种事件。
  • 指定事件代理的元素,如 $(document).off('click', '#example'),可以移除为该元素绑定的事件代理处理程序。

一次性事件

使用 .one() 方法绑定的事件处理程序只会触发执行一次,一次后自动移除:

$('#example').one('click', clickHandler);

事件节流

浏览器中有几个事件会频繁触发,比如 scroll, resize, mousemove 等,那么给这些事件绑定的事件处理程序也会跟着频繁地执行,导致页面反应迟钝,要解决这个问题,需要节流事件,减少事件处理程序执行的频率:

var timer = 0; // 使用一个定时器
$(window).on('scroll', function() {
 if (!timer) {
 timer = setTimeout(function() {
 // Do something
 timer = 0;
 }, 200);
 }
});

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
用js+xml自动生成表格的东西
Dec 21 Javascript
IE6不能修改NAME问题的解决方法
Sep 03 Javascript
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
Jan 15 Javascript
Javascript中call的两种用法实例
Dec 13 Javascript
JavaScript 异常处理 详解
Feb 06 Javascript
js实现带进度条提示的多视频上传功能
Dec 13 Javascript
详解Vue微信公众号开发踩坑全记录
Aug 21 Javascript
利用JS测试目标网站的打开响应速度
Dec 01 Javascript
vue+element树组件 实现树懒加载的过程详解
Oct 21 Javascript
微信公众号H5之微信分享常见错误和问题(小结)
Nov 14 Javascript
vue学习笔记之slot插槽用法实例分析
Feb 29 Javascript
Vue实现下拉加载更多
May 09 Vue.js
js实现固定宽高滑动轮播图效果
Jan 13 #Javascript
JavaScript利用闭包实现模块化
Jan 13 #Javascript
Vue.js基础知识小结
Jan 13 #Javascript
canvas实现流星雨的背景效果
Jan 13 #Javascript
JavaScript正则表达式替换字符串中图片地址(img src)的方法
Jan 13 #Javascript
原生js实现手风琴功能(支持横纵向调用)
Jan 13 #Javascript
JavaScript使用简单正则表达式的数据验证功能示例
Jan 13 #Javascript
You might like
php导出生成word的方法
2015/12/25 PHP
PHP入门教程之PHP操作MySQL的方法分析
2016/09/11 PHP
IE iframe的onload方法分析小结
2010/01/07 Javascript
jquery 无限级联菜单案例分享
2013/03/26 Javascript
JS中for循序中延迟加载动态效果的具体实现
2013/08/18 Javascript
用js实现in_array的方法
2013/11/05 Javascript
手机端网页点击链接触发自动拨打或保存电话的示例代码
2014/08/15 Javascript
js实现类似jquery里animate动画效果的方法
2015/04/10 Javascript
JavaScript中数组的22种方法必学(推荐)
2016/07/20 Javascript
将JSON字符串转换成Map对象的方法
2016/11/30 Javascript
详解springmvc 接收json对象的两种方式
2016/12/06 Javascript
利用select实现年月日三级联动的日期选择效果【推荐】
2016/12/13 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
2018/07/02 Javascript
Vue实现table上下移动功能示例
2019/02/21 Javascript
Bootstarp在pycharm中的安装及简单的使用方法
2019/04/19 Javascript
微信小程序中显示倒计时代码实例
2019/05/09 Javascript
Node.js操作MongoDB数据库实例分析
2020/01/19 Javascript
JavaScript forEach中return失效问题解决方案
2020/06/01 Javascript
javascript实现贪吃蛇小练习
2020/07/05 Javascript
微信小程序通过websocket实时语音识别的实现代码
2020/08/19 Javascript
初学Python函数的笔记整理
2015/04/07 Python
Django中URLconf和include()的协同工作方法
2015/07/20 Python
基于Python中单例模式的几种实现方式及优化详解
2018/01/09 Python
Python实现获取本地及远程图片大小的方法示例
2018/07/21 Python
在python中pandas的series合并方法
2018/11/12 Python
Python3 使用cookiejar管理cookie的方法
2018/12/28 Python
使用Python创建简单的HTTP服务器的方法步骤
2019/04/26 Python
python实现机器人卡牌
2019/10/06 Python
Pycharm自带Git实现版本管理的方法步骤
2020/09/18 Python
python实现AdaBoost算法的示例
2020/10/03 Python
Lookfantastic阿联酋官网:英国知名美妆护肤购物网站
2020/05/26 全球购物
高中生毕业自我鉴定
2013/10/10 职场文书
三问三解心得体会
2014/09/05 职场文书
2014年酒店年度工作总结
2014/12/10 职场文书
解决MySQL Varchar 类型尾部空格的问题
2022/04/06 MySQL
Java由浅入深通关抽象类与接口(下篇)
2022/04/26 Java/Android