1. 事件绑定
1.1 addEventListener
实现事件绑定
const btn = document.getElementById('btn1')
btn.addEventListener('click', event => {
console.log('clicked')
})
1.2 手写绑定函数
// 通用的绑定函数
function bindEvent(elem, type, fn){
elem.addEventListener(type, fn)
}
const a = document.getElementById('link1')
bindEvent(a, 'click', e=>{
e.preventDefault() // 阻止默认行为
alert('clicked')
})
1.3 示例
<!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>事件绑定</title>
<style>
div {
border: 1px solid #ccc;
margin: 10px 0;
padding: 0 10px;
}
</style>
</head>
<body>
<button id="btn1">一个按钮</button>
<script>
// 通用的绑定函数
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const btn1 = document.getElementById('btn1')
bindEvent(btn1, 'click', event =>{
console.log(event.target) // 获取触发的元素
event.preventDefault() // 阻止默认行为
alert('clicked')
})
</script>
</body>
</html>
2. 事件冒泡
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
<p id="p3">取消</p>
<p id="p4">取消</p>
</div>
<div id="div2">
<p id="p5">取消</p>
<p id="p6">取消</p>
</div>
<script>
// 通用的绑定函数
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const p1 = document.getElementById('p1')
const body = document.body
bindEvent(p1, 'click', event=>{
console.log('激活')
})
bindEvent(body, 'click', event=>{
console.log('body clicked')
})
</script>
事件冒泡的情况:点击“激活”的p标签,会触发p标签绑定的事件,同时也会触发body绑定的事件。
此时,我们在“激活”的p标签的绑定事件中加入stopPropagation()
,就可以防止事件冒泡。
<script>
// 通用的绑定函数
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const p1 = document.getElementById('p1')
const body = document.body
bindEvent(p1, 'click', event=>{
event.stopPropagation() // 阻止事件冒泡
console.log('激活')
})
bindEvent(body, 'click', event=>{
console.log('body clicked')
})
</script>
3. 事件代理
事件代理是利用了事件冒泡的机制完成的。当需要对多个元素绑定相同的事件时,可以将事件绑定在这些元素的父元素上,利用冒泡机制实现子元素的事件绑定。
事件代理的优点:
- 代码简洁
- 减少浏览器内存占用
<!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>事件代理</title>
</head>
<body>
<div id="div1">
<a href="#">a1</a><br>
<a href="#">a2</a><br>
<a href="#">a3</a><br>
<a href="#">a4</a><br>
</div>
<script>
function bindEvent(elem, type, fn){
elem.addEventListener(type, fn)
}
const div1 = document.getElementById('div1')
bindEvent(div1, 'click', event=>{
event.preventDefault() // 阻止跳转链接的默认行为
const target = event.target
if(target.nodeName === 'A'){
alert(target.innerHTML)
}
})
</script>
</body>
</html>
4. 通用的事件绑定函数
function bindEvent(elem, type, selector, fn){
if(fn == null){
fn = selector
selector = null
}
elem.addEventListener(type, event=>{
const target = event.target
if(selector){
// 代理绑定
if(target.matches(selector)){
fn.call(target, event)
}
}else{
// 普通绑定
fn.call(target, event)
}
})
}