「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
基本概念
定义:事件是在编程时系统内发生的动作或者发生的事情——系统会在事件出现时产生或触发某种信号,并且会提供一个自动加载某种动作(列如:运行一些代码)的机制。
在 Web 中, 事件在浏览器窗口中被触发并且通常被绑定到窗口内部的特定部分 — 可能是一个元素、一系列元素、被加载到这个窗口的 HTML 代码或者是整个浏览器窗口。举几个可能发生的不同事件:
- 用户在某个元素上点击鼠标或悬停光标。
- 用户在键盘中按下某个按键。
- 用户调整浏览器的大小或者关闭浏览器窗口。
- 提交表单。
- 播放、暂停、关闭视频。
每个可用的事件都会有一个事件处理器,也就是事件触发时会运行的代码块。当我们定义了一个用来回应事件被激发的代码块的时候,我们说我们注册了一个事件处理器。注意事件处理器有时候被叫做事件监听器
使用网页事件的方式
可以通过多种不同的方法将事件监听器代码添加到网页,以便在关联的事件被触发时运行它。
HTML属性(不建议使用)
行内事件处理器,处理程序可以设置在 HTML 中名为 on<event>
的特性(attribute)中。
例如:onclick="alert('Click!')"
<input value="Click me" onclick="alert('Click!')" type="button">
在鼠标点击时,onclick
中的代码就会运行。
注意,在
onclick
中,要使用单引号,因为特性本身使用的是双引号。如果忘记了代码是在特性中的,而使用了双引号,像这样:onclick="alert("Click!")"
,那么它将无法正确运行。
DOM属性
可以使用 DOM 属性(property)on<event>
来分配处理程序。
例如:elem.onclick
const btn = document.querySelector('button');
btn.onclick = function() {
const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
}
这个onclick
是被用在这个情景下的事件处理器的属性,它就像 button 其他的属性(如btn.style),但是有一个特别的地方,当把一些代码赋值给它的时候,只要事件触发代码就会运行。
可以将一个有名字的函数赋值给事件处理参数
function sayThanks() {
alert('Thanks!');
}
elem.onclick = sayThanks;
注意:函数不加括号,如果添加了括号,那么 sayThanks()
就变成了一个函数调用。
// 正确✔️
button.onclick = sayThanks;
// 错误❌
button.onclick = sayThanks();
扩展
如果同时用HTML属性和DOM属性添加事件,执行的是谁?
后面的事件会覆盖前面的。
<input type="button" id="elem" onclick="alert('Before')" value="Click me">
<script>
elem.onclick = function() { // 覆盖了现有的处理程序
alert('After'); // 只会显示此内容
};
</script>
注意大小写问题!
- html属性,大小写不敏感。
ONCLICK
和onClick
以及onCLICK
都一样可以运行。但是特性通常是小写的:onclick
。 - DOM属性,大小写敏感,只能写
elem.onclick
,像这种elem.ONCLICK
是不行的。
addEventListener
EventTarget.addEventListener() 方法是将指定的事件监听器注册到目标对象上,当该对象触发指定的事件时,指定的回调函数就会被执行。
添加监听事件
语法:element.addEventListener(event, listener[, options]);
event:事件名,例如:"click"。
listener:处理程序。
options:具有以下属性的附加可选对象:
- once:如果为 true,那么会在被触发后自动删除监听器。
- capture:事件处理的阶段(true 事件捕获 false 事件冒泡)。
- passive:如果为 true,那么处理程序将不会调用 preventDefault()
移除监听事件
语法:element.removeEventListener(event, handler[, options]);
示例
/**部分代码**/
//添加
myElement.addEventListener('click', functionA);
//移除
myElement.removeEventListener('click', functionA);
关于第三个参数的使用之冒泡和捕获
elem.addEventListener(..., {capture: true})
或者,用 {capture: true} 的别名 "true" elem.addEventListener(..., true)
//后面文章会细说这两个
myElement.addEventListener('click', functionA); //冒泡
myElement.addEventListener('click', functionA, true); //捕获
handleEvent
上面说到的addEventListener()
中的listener
:当指定的事件类型发生时被通知到的一个对象。
该参数必须是实现EventListener接口的一个对象或函数。即,第二个参数除了可以传入函数外,还可以传入对象。
interface EventListener {
// 注意:该接口属于DOM2, 所以IE6~IE8不能直接使用
void handleEvent(Event evt);
};
也就是说事件会自动在传入对象中寻找handleEvent方法。
所以你可以把所有事件都写到一个obj当中,根据事件类型区分,而不用为每个事件类型定义不同的处理函数。
示例:
var obj = {
handleEvent: function(e) {
switch(e.type) {
case "click":
this.demoClick(event);
break;
case "mousedown":
this.demoMousedown(event);
break;
}
},
demoClick:function(event){ console.log("点击事件");},
demoMousedown:function(event){ console.log("按下鼠标"); },
};
document.body.addEventListener('click', obj, false);
document.body.addEventListener('mousedown', obj, false);
事件对象event
当事件发生时,浏览器会创建一个 event
对象,将详细信息放入其中,并将其作为参数传递给处理程序。
比如点击事件
<input type="button" value="Click me" id="elem">
<script>
elem.onclick = function(event) {
console.log(event);
};
</script>
部分打印结果:
event
对象的一些属性:
event.type
:事件类型,这里是"click"
。event.currentTarget
:处理事件的元素。这与this
相同,除非处理程序是一个箭头函数,或者它的this
被绑定到了其他东西上,之后我们就可以从event.currentTarget
获取元素了。event.clientX / event.clientY
:指针事件(pointer event)的指针的窗口相对坐标。
参考资料:
Introduction to browser events
🎨【点赞】【关注】不迷路,更多前端干货等你解锁
往期推荐