事件介绍 上一页 概述:创建 JavaScript 代码块 下一页
事件是你正在编程的系统中发生的事情,系统会告诉你有关这些事件的信息,以便你的代码能够对它们做出反应。
例如:如果用户在网页上单击一个按钮,你可能想通过显示一个信息框来响应这个动作。在这篇文章中,我们将讨论一些关于事件的重要概念,并且观察它们在浏览器上如何运行。这篇文章不会面面俱到,仅聚焦于你现阶段需要掌握的知识。
前提:
基本的计算机知识,对 HTML 和 CSS 的基本了解,学习了 JavaScript 第一步。
目标:
了解事件的基本理论,它们怎么在浏览器上运行的,以及在不同的编程环境下事件有何不同。
什么是事件?事件是发生在你正在编程的系统中的事情——当事件发生时,系统产生(或“触发”)某种信号,并提供一种机制,当事件发生时,可以自动采取某种行动(即运行一些代码)。事件是在浏览器窗口内触发的,并倾向于附加到驻留在其中的特定项目。这可能是一个单一的元素,一组元素,当前标签中加载的 HTML 文档,或整个浏览器窗口。有许多不同类型的事件可以发生。
例如:
用户选择、点击或将光标悬停在某一元素上。
用户在键盘中按下某个按键。
用户调整浏览器窗口的大小或者关闭浏览器窗口。
网页结束加载。
表单提交。
视频播放、暂停或结束。
发生错误。
你可以从这里(以及从 MDN 事件参考文档)中看出,有相当多的事件可以被触发。
为了对一个事件做出反应,你要给它附加一个事件处理器。这是一个代码块(通常是你作为程序员创建的一个 JavaScript 函数),在事件发生时运行。当这样一个代码块被定义为响应一个事件而运行时,我们说我们在注册一个事件处理器。注意,事件处理器有时候被叫做事件监听器——从我们的用意来看这两个名字是相同的,尽管严格地来说这块代码既监听也处理事件。监听器留意事件是否发生,处理器对事件发生做出回应。
备注:
web 事件不是 JavaScript 语言的核心——它们被定义成内置于浏览器的 API。
示例:处理点击事件在这个示例中,我们在页面中有一个
html
button {
margin: 10px;
}
然后我们有一些 JavaScript。我们将在下一节中更详细地讨论这个问题,但现在我们可以说:它为按钮的 "click" 事件添加了一个事件处理器,该处理器对该事件的反应是将页面背景设置为随机颜色:
jsconst btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.addEventListener("click", () => {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
});
示例输出如下,试试点击按钮吧:
使用 addEventListener()正如我们在上一个示例中所看到的,能够触发事件的对象有一个 addEventListener() 方法,这就是推荐的添加事件处理器的机制。
让我们仔细看一下上一个示例的代码:
jsconst btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.addEventListener("click", () => {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
});
HTML
字符串 "click",表示我们要监听点击事件。按钮可以触发很多其他的事件,比如当用户将鼠标移到按钮上时("mouseover" 事件),或者当用户按下一个键并且按钮被聚焦时("keydown" 事件)。
当事件发生时所调用的函数。在我们的例子中,该函数生成一个随机的 RGB 颜色,并将页面
的 background-color 设置为该颜色。把处理函数作为一个单独的具名函数也是可以的,像这样:
jsconst btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
function changeBackground() {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
btn.addEventListener("click", changeBackground);
监听其他事件有许多不同的事件可以由一个按钮元素来触发。让我们来做个实验。
首先,在本地创建 random-color-addeventlistener.html 的副本,并在浏览器中打开。这只是我们已经玩过的简单的随机颜色示例的一个副本。现在试着依次将 click 改为以下不同的值,并观察示例中的结果:
focus 和 blur:当按钮被聚焦或失焦时,颜色会改变;尝试按下 tab 键来聚焦于按钮,再次按下该键来使按钮失去焦点。这些事件通常用于在聚焦时显示填入表单字段的信息,或者在表单字段填入不正确的值时显示错误信息。
dblclick:颜色只在按钮被双击时改变。
mouseover 和 mouseout:当鼠标指针在按钮上悬停,或指针移出按钮时,颜色分别会改变。
一些事件,如 click(点击事件),几乎对任何元素都可用。其他事件则更具体,只在某些情况下有用:例如,play 事件只对某些元素有效,如
移除监听器如果你使用 addEventListener() 添加了一个事件处理器,你可以使用 removeEventListener() 方法再次删除它。例如,这将删除 changeBackground() 事件处理器:
jsbtn.removeEventListener("click", changeBackground);
事件处理器也可以通过传递 AbortSignal 到 addEventListener(),然后在拥有 AbortSignal 的控制器上调用abort(),从而删除事件处理器。例如,要添加一个可以使用 AbortSignal 来删除的事件处理器,可以这样做:
jsconst controller = new AbortController();
btn.addEventListener("click",
() => {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
},
{ signal: controller.signal } // 向该处理器传递 AbortSignal
);
然后可以像这样删除上面代码创建的事件处理器:
jscontroller.abort(); // 移除任何/所有与该控制器相关的事件处理器
对于简单的小程序,清理旧的、未使用的事件处理器是没有必要的,但对于更大的、更复杂的程序,它可以提高效率。另外,删除事件处理器的能力允许你让同一个按钮在不同的情况下执行不同的动作:你所要做的就是添加或删除处理程序。
在单个事件上添加多个监听器通过对 addEventListener() 的多次调用,每次提供不同的处理器,你可以为一个事件设置多个处理器:
jsmyElement.addEventListener("click", functionA);
myElement.addEventListener("click", functionB);
当点击按钮时,所有处理器函数都会运行。
了解更多对于 addEventListener() 来说,还有很多强大的特性和选项。
这些有些超出了本文的范畴,如果你想了解更多,请参见 addEventListener 和 removeEventListener() 参考页面。
其他事件监听器机制我们推荐你使用 addEventListener() 来注册事件处理器。这是最强大的方法,在更复杂的程序中,它的扩展性最好。然而,还有两种注册事件处理器的方法,你可能会看到:事件处理器属性和内联事件处理器。
事件处理器属性可以触发事件的对象(如按钮)通常也有属性,其名称是 on,后面是事件的名称。例如,元素有一个属性 onclick。这被称为事件处理器属性。为了监听事件,你可以将处理函数分配给该属性。
例如,我们可以像这样重写随机颜色示例:
jsconst btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.onclick = () => {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
};
你也可以将处理器属性分配给具名函数:
jsconst btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
function bgChange() {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
btn.onclick = bgChange;
对于事件处理器属性,你不能为一个事件添加一个以上的处理程序。例如,你可以在一个元素上多次调用 addEventListener('click', handler),并在第二个参数中指定不同的函数:
jselement.addEventListener("click", function1);
element.addEventListener("click", function2);
对于事件处理器属性来说,这是不可能的,因为任何后续尝试都会覆写较早设置的属性:
jselement.onclick = function1;
element.onclick = function2;
内联事件处理器——不要使用你可能也会在代码中看到这种形式:
html
jsfunction bgChange() {
const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
在 web 上发现的最早的注册事件处理器的方法涉及到事件处理器 HTML 属性(或内联事件处理器),如示例所示。属性值就是你想在事件发生时运行的 JavaScript 代码。上面的示例调用了同一页面上