详解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 相关文章推荐
JScript的条件编译
May 29 Javascript
js DataSet数据源处理代码
Mar 29 Javascript
Jquery.TreeView结合ASP.Net和数据库生成菜单导航条
Aug 27 Javascript
jQuery实现3D文字特效的方法
Mar 10 Javascript
JavaScript中的this到底是什么(一)
Dec 09 Javascript
BootStrap实现带关闭按钮功能
Feb 15 Javascript
浅析JS中常用类型转换及运算符表达式
Jul 23 Javascript
webpack多入口文件页面打包配置详解
Jan 09 Javascript
JavaScript实现简单轮播图效果
Dec 01 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
Mar 08 Javascript
SpringBoot+Vue开发之Login校验规则、实现登录和重置事件
Oct 19 Javascript
three.js如何实现3D动态文字效果
Mar 03 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
为IP查询添加GOOGLE地图功能的代码
2010/08/08 PHP
在PHP中运行Linux命令并启动SSH服务的例子
2014/06/12 PHP
ThinkPHP模板引擎之导入资源文件方法详解
2014/06/18 PHP
php绘制一个矩形的方法
2015/01/24 PHP
Yii2隐藏frontend/web和backend/web的方法
2015/12/12 PHP
Laravel重定向,a链接跳转,控制器跳转示例
2019/10/22 PHP
PHP实现简单登录界面
2019/10/23 PHP
JavaScript判断窗口是否最小化的代码(跨浏览器)
2010/08/01 Javascript
jQuery UI的Dialog无法提交问题的解决方法
2011/01/11 Javascript
Angular的Bootstrap(引导)和Compiler(编译)机制
2016/06/20 Javascript
JavaScript学习笔记整理_用于模式匹配的String方法
2016/09/19 Javascript
Kendo Grid editing 自定义验证报错提示的解决方法
2016/11/18 Javascript
jQuery实现下拉菜单的实例代码
2017/06/19 jQuery
jQuery实现上传图片前预览效果功能
2017/08/03 jQuery
小程序图片剪裁加旋转的示例代码
2018/07/10 Javascript
vue-cli 默认路由再子路由选中下的选中状态问题及解决代码
2018/09/06 Javascript
Vue.js组件间通信方式总结【推荐】
2018/11/23 Javascript
vue-cli中vue本地实现跨域调试接口
2019/01/16 Javascript
vue-cli在 history模式下的配置详解
2019/11/26 Javascript
python多线程编程方式分析示例详解
2013/12/06 Python
200行python代码实现2048游戏
2019/07/17 Python
python通过robert、sobel、Laplace算子实现图像边缘提取详解
2019/08/21 Python
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
你的自行车健身专家:FaFit24
2016/11/16 全球购物
AJAX都有哪些有点和缺点
2012/11/03 面试题
写演讲稿所需要注意的4个条件
2014/01/09 职场文书
电气工程及其自动化专业毕业生自荐信
2014/06/21 职场文书
个人合伙协议书范本
2014/10/14 职场文书
综治维稳工作汇报
2014/10/27 职场文书
解除劳动关系协议书2篇
2014/11/28 职场文书
职代会闭幕词
2015/01/28 职场文书
个人业务学习心得体会
2016/01/25 职场文书
[有人@你]你有一封绿色倡议书,请查收!
2019/07/18 职场文书
python tkinter Entry控件的焦点移动操作
2021/05/22 Python
Python实现简单得递归下降Parser
2022/05/02 Python
win10忘记pin密码登录不了怎么办?win10忘记pin密码登不进去的解决方法
2022/07/07 数码科技