概述
2022年10月14日大约 4 分钟
事件 是某事发生的信号,所有的 DOM 节点都生成这样的信号
为了对事件作出响应,需分配一个 处理程序,一个在事件发生时运行的函数
处理程序可以设置在 HTML 中名为
on<event>
的属性中elem.onclick = null
:移除一个事件处理程序
相关文档
事件对象(event)
当事件发生时,浏览器会创建一个
event
对象,将详细信息放入其中,并将其作为参数传递给处理程序
event.type
事件类型,例如
click
event.currentTarget
处理事件的元素,与
this
相同除非处理程序是一个箭头函数,或者它的
this
被绑定到了其他东西上,之后可以从event.currentTarget
获取元素
event.clientX / event.clientY
指针事件(pointer event)的指针的窗口相对坐标
addEventListener
注册 click 事件
同一元素的同一阶段的监听器按其设置顺序运行
要移除处理程序,
removeEventListener
需要同一阶段语法:
element.addEventListener(event, handler[, options]);
event
:事件名handle
:处理程序(函数)options
:可选参数对象,属性如下once
:如果为 true,会在事件被触发后删除监听器capture
:事件处理的阶段,由于历史原因,options
也可以是false/true
,它与{capture: false/true}
相同- 如果为
false
(默认值),则在冒泡阶段设置处理程序 - 如果为
true
,则在捕获阶段设置处理程序
- 如果为
passive
:如果为true
,那么处理程序将不会调用preventDefault()
,告诉浏览器该行为不会被阻止。这对于某些移动端的事件(像 touchstart 和 touchmove)很有用,用以告诉浏览器在滚动之前不应等待所有处理程序完成
<button id="btn">测试事件</button>
<script type="text/javascript">
var oBtn = document.getElementById('btn')
oBtn.addEventListener('click',btnClick,{once:true})
function btnClick(){
console.log('click')
}
</script>
将对象作为处理程序
当
addEventListener
接收一个对象obj
作为处理程序时,在事件发生时,它就会调用obj.handleEvent(event)
来处理事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div {
width: 200px;
height: 200px;
border: 1px solid #000;
background: #f3f3f3;
text-align: center;
line-height: 200px;
font-size: 24px;
}
</style>
</head>
<body>
<div id="div"></div>
<script type="text/javascript">
class Menu {
handleEvent(event) {
const method = `on${event.type[0].toUpperCase()}${event.type.slice(1)}`
this[method](event)
}
onMousedown(event) {
console.log(event.target)
event.target.innerHTML = 'mousedown'
}
onMouseup(event) {
event.target.innerHTML = 'mouseup'
}
onMouseout(event) {
event.target.innerHTML = ''
}
}
var oDiv = document.getElementById('div')
var menu = new Menu()
oDiv.addEventListener('mousedown', menu)
oDiv.addEventListener('mouseup', menu)
oDiv.addEventListener('mouseout', menu)
</script>
</body>
</html>
与 onclick 的区别
- 直接写 onclick 事件在同一时间只能指向唯一对象,后面写的会覆盖前面的
- addEventListener 可以给一个事件注册多个 listener,且均可执行
- addEventListener 可以使用 removeEventListener 清除
- JQuery 与 addEventListener 一样可以注册多个事件,且均可执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="clickme">Click me!</button>
<div id="message"></div>
<script src="js/jquery.js"></script>
<script>
var oBtn = document.getElementById('clickme')
function btnClick() {
console.log('button click')
}
function btnClickClick() {
console.log('button click click')
}
/**
* onclick 直接绑定
*/
oBtn.onclick = btnClick
oBtn.onclick = btnClickClick
/**
* addEventListener 注册事件
*/
oBtn.addEventListener('click', btnClick)
oBtn.addEventListener('click', btnClickClick)
// 清除 addEventListener 注册的事件
setTimeout(() => {
oBtn.removeEventListener('click', btnClickClick)
console.log('removeEventListener success')
}, 5000)
/**
* JQuery 绑定事件
*/
$('#clickme').click(btnClick)
$('#clickme').click(btnClickClick)
</script>
</body>
</html>
例子
球体区域点击定位
小球在矩形内部,点击矩形任意一点,将球中心定位到该店,并且小球仅在矩形内部移动
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
#field {
position: relative;
width: 300px;
height: 300px;
border: 10px solid black;
background: #00FF00;
overflow: hidden;
cursor: pointer;
}
#ball {
position: absolute;
left: 0;
top: 0;
width: 40px;
height: 40px;
transition: all 1s;
}
</style>
</head>
<body style="height:2000px">
Click on a field to move the ball there.
<br>
<div id="field">
<img src="https://en.js.cx/clipart/ball.svg" id="ball">
</div>
<script>
var oField = document.getElementById('field')
oField.addEventListener('click', handleChange)
function handleChange(event) {
// div相对于窗口的坐标
let fieldCoords = this.getBoundingClientRect();
console.log(fieldCoords)
// top: 点相对于窗口的纵坐标 - 矩形顶部的纵坐标 - 矩形上边框 - 球高度的一半
// left: 点相对于窗口的横坐标 - 矩形左边缘的横坐标 - 矩形左边框 - 球宽度的一半
let ballCoords = {
top: event.clientY - fieldCoords.top - field.clientTop - ball.clientHeight / 2,
left: event.clientX - fieldCoords.left - field.clientLeft - ball.clientWidth / 2
};
// 保证球体顶部边缘在矩形内部
if (ballCoords.top < 0) ballCoords.top = 0;
// 保证球体左部边缘在矩形内部
if (ballCoords.left < 0) ballCoords.left = 0;
// 保证球体右部边缘在矩形内部
if (ballCoords.left + ball.clientWidth > field.clientWidth) {
ballCoords.left = field.clientWidth - ball.clientWidth;
}
// 保证球体底部边缘在矩形内部
if (ballCoords.top + ball.clientHeight > field.clientHeight) {
ballCoords.top = field.clientHeight - ball.clientHeight;
}
// 设置球体样式
ball.style.left = ballCoords.left + 'px';
ball.style.top = ballCoords.top + 'px';
}
</script>
</body>
</html>