详解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 相关文章推荐
jQuery Tools tab(幻灯片)
Jul 14 Javascript
javascript调试过程中找不到哪里出错的可能原因
Dec 16 Javascript
快速解决jQuery与其他库冲突的方法介绍
Jan 02 Javascript
jQuery实现鼠标可拖动调整表格列宽度
May 26 Javascript
javascript嵌套函数和在函数内调用外部函数的区别分析
Jan 31 Javascript
bootstrap下拉列表与输入框组结合的样式调整
Oct 08 Javascript
js实现textarea限制输入字数
Feb 13 Javascript
详解Webpack多环境代码打包的方法
Aug 03 Javascript
解决koa2 ctx.render is not a function报错问题
Aug 07 Javascript
使用layui监听器监听select下拉框,事件绑定不成功的解决方法
Sep 28 Javascript
js get和post请求实现代码解析
Feb 06 Javascript
浅谈JSON5解决了JSON的两大痛点
Dec 14 Javascript
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
VFP与其他应用程序的集成
2006/10/09 PHP
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
linux系统下php安装mbstring扩展的二种方法
2014/01/20 PHP
JavaScript获取网页中第一个图片id的方法
2015/04/03 Javascript
详解AngularJS中的表格使用
2015/06/16 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
react-router v4如何使用history控制路由跳转详解
2018/01/09 Javascript
bootstrap模态框关闭后清除模态框的数据方法
2018/08/10 Javascript
Iview Table组件中各种组件扩展的使用
2018/10/20 Javascript
微信小程序中插入激励视频广告并获取收益(实例代码)
2019/12/06 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
JS如何实现网站中PC端和手机端自动识别并跳转对应的代码
2020/01/08 Javascript
微信小程序实现滑动操作代码
2020/04/23 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
DWR内存兼容及无法调用问题解决方案
2020/10/16 Javascript
TensorFlow神经网络优化策略学习
2018/03/09 Python
python版大富翁源代码分享
2018/11/19 Python
Python用字典构建多级菜单功能
2019/07/11 Python
python3实现elasticsearch批量更新数据
2019/12/03 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
简述Html5 IphoneX 适配方法
2018/02/08 HTML / CSS
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
澳大利亚最便宜的网上药房:Chemist Warehouse
2020/01/30 全球购物
医学专业毕业生个人求职信
2013/12/25 职场文书
应届行政管理专业个人自我评价
2013/12/28 职场文书
客户服务经理岗位职责
2014/01/29 职场文书
日语专业求职信
2014/07/04 职场文书
研究生导师推荐信
2014/09/06 职场文书
教育局党的群众路线教育实践活动整改方案
2014/09/20 职场文书
幼儿园小班开学寄语
2015/05/27 职场文书
2016年大学生暑期社会实践方案
2015/11/26 职场文书
JavaScript使用canvas绘制坐标和线
2021/04/28 Javascript
golang switch语句的灵活写法介绍
2021/05/06 Golang
Pytorch 如何实现常用正则化
2021/05/27 Python
Python实现学生管理系统并生成exe可执行文件详解流程
2022/01/22 Python
box-shadow单边阴影的实现
2023/05/21 HTML / CSS