每周获取最新的 Wordpress 资源

Jquery 事件对象和事件委托

事件(Event)

网页中什么是事件呢?了解这个问题,我们可以先回想我们实际生活中的每个时刻,比如说,篮球入框的时刻,短跑运动员跑过终点的时刻。然后我们再看看,在网页中事件是什么?比如说,当点击某个按钮时,当鼠标滚动到某个位置时,当鼠标悬浮在某个元素时等等,这些都是事件。

Javascript 或者 jQuery 都可以监听某个事件,以及对某个事件作出响应,我们来了解下监听事件和响应必备三项:

  1. 被监听的目标元素
  2. 要作出回应的事件
  3. 要在响应中采取的具体行动

举个 jQuery 中的一个具体的监听并作出响应的例子:

jQuery('.menu li').on('hover', function() {
    $(this).addClass('active');
});

在上面这个例子中,被监听的目标元素为:.menu li,要作出回应的事件:hover,在响应中采取的具体行动:$(this).addClass('active');

然后再了解一个在浏览器中调试和了解事件的小技巧,使用 chrome 浏览器底层 V8 引擎中的 monitorEvents() 自带函数,可以监视发生在自定义选取元素的所有事件,注意这个函数仅可以在 V8 引擎的浏览器 console 中使用,无法在你的项目中使用。例如:

var img = $("img");
var firstimg = img[0];
monitorEvents(firstimg);

事件对象(Event Object)

对事件作出回应通常需要事件本身相关的知识,因此下面我们将对事件对象做一个简要介绍。

首先,了解一下,事件对象是会传递到事件侦听器回调函数的,我们将在回调函数中,来看看事件对象具体是什么,以及可以做什么?

需要记住的是,当事件发生时,目标元素将调用回调函数。而当回调函数被调用时,jQuery 就会传递一个包含事件相关信息的事件对象给它。这个对象包含非常多的有用信息可以使用。此对象通常在 JavaScript 中被引用为 e、evt 或 event,它的一些属性可以用来决定你的代码流程。尝试打印出这个对象来查看可用属性:

jQuery('article').on('click', function(evt) {
    console.log(evt);
});

从上面打印出的信息,你应该注意到了有一个 target 属性。这个属性会包含作为事件目标的某个页面元素的信息。如果已经为一定数目的页面元素设置了一个事件监听器,这个 target 属性会非常的有用。

jQuery('article').on('click', function(evt) {
    jQuery(evt.target).css('background', 'red');
});

在上面的例子中,在页面中为每一个 article 元素设置了一个事件监听器。当某一个 article 元素被点击之后,带有这个事件信息的对象就会被传给回调函数。evt.target 可以用来获取刚刚在 article 元素内被点击的部分,然后使用 jQuery 选择这个部分,将它的背景更新为红色。

在你想阻止浏览器将执行的默认操作时,事件对象也会派上用场。比如说一个链接的默认点击事件是,跳转到某个页面,如果我们给它加个点击事件,让它做其他事情,而不是跳转到其他页面,比如在控制台中打印出一条信息等等,这时候就需要使用事件对象:

$('#myAnchor').on('click', function(evt) {
    evt.preventDefault();
    console.log('You clicked a link!');
});

其实还有很多其他的事件对象也很有用,比如说:

  • event.keyCode 用来了解按了哪个键 — 当你需要监听一个特定的键时,就显得非常有有用。
  • event.pageXevent.pageY 可以用来了解某个页面中的点击是在哪里发生的,获取具体的 x 轴和 y 轴的值 — 当分析追踪用户行为时非常的有用。
  • event.type 用来了解发生了哪种类型的事件 — 在监听目标的多个事件时会非常的有用。

更多请参考下面的文章:

jQuery's Event Object
event.target property
DOM Level 3 Events

事件委托(Event Delegation)

到目前为止,我们已经了解了在 jQuery 中如何进行事件监听和响应:用 jQuery 获取目标元素,然后将事件监听器绑定到该目标元素,然后进行具体操作。但是,你有没有考虑过或者遇到过一种情况,就是当目标元素是含有多个项目的列表,并且你希望监听任意项目的点击次数,在页面加载完毕后,通过 jQuery 向这个列表又增加了额外一个列表项,这时候,能监听到这个额外列表项的点击次数吗?会发生什么?

在设置事件监听器之后创建目标项目时,需要小心你的代码对于新增项不再起作用,看个具体实例:

$('article').on('click', function() {
    $('body').addClass('selected');   
});

$('body').append('<article> <h1>Appended Article</h1> <p>Content for the new article </p> </article>');

上面这段代码,点击新增的 article 目标元素并不会给 body 增加一个 class。因为,这个 article 是在置事件监听器之后才创建的。

但是这个问题可以通过事件委托来解决。具体做法就是,我们监听点击 article 父元素的事件,然后留意这些事件的具体目标。jQuery 中的事件委托的实现使用上面相同的代码,只不过给 on 方法传入一个额外的参数。代码如下:

$('.container').on('click', 'article', function() { … });

上面这段代码的意思就是:使用 jQuery 监听 .container 元素中的点击事件,如果有任何点击,那么检查事件目标是否是 article 元素。这样一来,无论你的这个 article 元素是否是新建的,都不影响。

使用事件委托的另外一个优点是,你可以使用它来合并事件监听器的数量。例如,如果在一个页面上有 1000 个列表项:

<ul id="rooms">
    <li>Room 1</li>
    <li>Room 2</li>
            .
            .
            .
    <li>Room 999</li>
    <li>Room 1000</li>
</ul>

不使用 jQuery 事件委托的话,以下代码将为每个列表项都设置一个事件监听器,总计 1000 个事件监听器!

$( '#rooms li' ).on( 'click', function() {
    // some code here
});

使用 jQuery 的事件委托,仅会在一个元素 (#rooms) 上设置事件监听器,并检查目标元素是否为列表项。

$( '#rooms' ).on( 'click', 'li', function() {
    // some code here
});

了解更多关于事件委托,请查看:Event Delegation

You May Also Like

About the Author: ted

发表评论

电子邮件地址不会被公开。 必填项已用*标注