无标题文章

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <script type="text/javascript" src=""></script>
    <title>Document</title>
    <style type="text/css">
        .main {
            width: 200px;
            height: 200px;
            border: 1px solid red;
            background: green;
        }

        .add {
            background: red;
        }
    </style>
    <script type="text/javascript">
        $(function() {
            $(".clk").on('haha', function() {
                $(".main").toggleClass('add');
            });
            setInterval(function() {
                $(".clk").trigger('haha');
            },1000);
        })
    </script>
</head>

<body>
    <div class="main"></div>
    <button class="clk">click</button>
</body>

</html>

事件是 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);
}
});

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 好的用户界面-界面设计的一些技巧( 原文地:Good UIhttp://goodui.org ) 1 尽量使用单列...
    荷尔蒙阅读 555评论 0 1
  • Javascript中的事件委托和代理 当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事...
    Wendy81阅读 200评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • 罗裳轻解入帷幔, 淡菊风吹低羞颜, 幽幽频送上阁阑, 拥着暗香入梦来。
    海客鱼鱼阅读 292评论 0 0
  • 秋日黄昏 徐家兴 那抹血色的残照把树梢点染的 有些忘记敲响 风的呼叫 摇着鞭子的老农真的就在山丫 点起了篝火 想和...
    赤脚老怪阅读 157评论 0 2