#13: 事件入门

处理事件是使用 jQuery 的另一个重要原因。在跨浏览器环境中,处理事件的方式有所不同,而 jQuery 将它们规范化为一个简单的 API,同时强制执行一些最佳实践。

您只需要了解一种方法:.on()——它的工作方式如下

$("button").on("click", function() {
  // do something
});

这里,我们只为 .on() 方法提供了两个参数。事件的名称(“click”)和在该事件发生在该选择器中的任何元素上时运行的函数。读起来很简洁,对吧?

具有一定 jQuery 经验的人可能熟悉其他绑定方法,如 .bind().live().delegate()。现在不用再担心它们了,现代 jQuery 已将它们全部合并到 .on() 中,它始终执行最佳实践。

当绑定事件时,就像我们在上面所做的那样,您可以在函数中包含一个参数名称(通常这样做是明智的)。该参数将在函数内部变成“事件对象”。

$("button").on("click", function(event) {
  // event => "the event object"
});

通过事件对象,您可以获得大量信息。您已经对其有所了解,因为我们使用它来执行 .preventDefault().stopPropagation()。但是,该对象中还有很多其他直接的信息。例如,事件的类型(如果多个事件触发同一个函数)、事件发生的时刻、事件发生的位置(坐标,如果适用)、事件发生的元素以及更多。在编码时,定期检查事件对象非常有用。

事件委托的概念在处理事件时非常重要。这是现代最佳实践中非常聪明的一种做法。它包含了范围的概念。

传统的事件绑定思维方式是“查找页面上的所有按钮,并为它们绑定一个点击事件”。当然,这种方法有效,但它

  • 效率不高
  • 脆弱

效率不高,因为您立即强制 JavaScript 查找所有这些按钮元素,而使用委托,您只需要查找一个更容易找到的元素。

脆弱,因为如果页面中添加了更多按钮,它们会错过绑定,需要重新绑定。

使用事件委托,您可以将该点击事件绑定到 DOM 树中比发生点击的按钮更高的元素。可能是某个 <div>,也可能是 document 本身。当您将点击事件绑定到该上级元素时,您可以告诉它,您仍然只对发生在按钮上的点击事件感兴趣。然后,当点击按钮时,通过事件冒泡的性质,该点击事件最终会触发上级元素。但是,事件对象会知道原始点击事件是否发生在按钮上,您设置的要在该事件上触发的函数将根据该信息决定是否触发。

在本屏幕录像中,我们这样演示

<div id="scope">
  <textarea></textarea>
</div>
$("#scope").on("click", "textarea", function(event) {
  
  // Do stuff!
  console.log(event);
  
});

现在想象一下,我们向该 <div id="scope"> 添加了另一个 <textarea>。我们无需重新绑定任何事件,因为事件仍然愉快地绑定到该范围,并且事件仍将从新添加的 textarea 冒泡。这在 Web 应用程序环境中特别有用,因为您会定期向页面添加新元素。

关于 jQuery 事件绑定的另一个好消息是,它们不是互斥的。如果您向同一个元素添加另一个点击处理程序,该元素已经有一个,它只会添加另一个。您不会覆盖之前的处理程序。jQuery 为您优雅地处理了这种情况。您始终可以取消绑定它们,如果您确实想覆盖之前绑定的函数。

如果是完全相同的事件,值得知道的是,为了取消绑定其中一个,而不是另一个,您需要为事件命名空间。这通过在事件名称中使用点来实现,例如 click.namespace

$("#scope").on("click.one", "textarea", function(event) {  });
$("#scope").on("click.two", "textarea", function(event) {  });

// Just remove the first
$("#scope").off("click.one", "textarea");

.off(),正如我们之前没有提到过的那样,是用来取消绑定事件的。

有很多可能的 DOM 事件。Click 是最主要、最明显的事件,但还有双击、mouseenter 和 mouseleave、keydown 和 keyup、表单相关的事件,如 blur 和 change,以及大量其他事件。如果您对完整列表感兴趣,您可以通过以下方式获取它。

您可以同时绑定多个事件,如下所示

$("#scope").on("keydown keyup", "textarea", function(event) {
  console.log(event.keyCode); 
});

在某些情况下,您在等待事件发生,但一旦事件发生,您就不再关心它,或者明确地不想再触发您已绑定的函数。这就是 .one() 函数的用途。一个标准的用例是表单提交按钮(如果您使用 Ajax 或其他方式处理)。您可能希望在用户按下提交按钮后将其禁用,直到您能够处理这些信息并为他们提供相应的反馈。当然,这不是唯一的用例,但请记住这一点。.one() == 只执行一次。