w3c事件模型中的事件:首先是捕获阶段,达到目标阶段,再进入冒泡阶段。
attachEvent()采用冒泡方式,而addEventListener()可以采用冒泡或事件捕获方式
document.body.addEventListener('click', ()=>{}, true)
事件冒泡
事件开始的节点元素接收,然后传播至上级
举个栗子:
层级关系: document > html > body > div > span > button
<!DOCTYPE html>
<html>
<body>
<div onclick="divClick()">
<span onclick="spanClick()">
<button onclick="butClick()">点击</button>
</span>
</div>
</body>
<script>
function butClick() {
console.log('button');
}
function spanClick() {
console.log('span');
}
function divClick() {
console.log('div');
}
document.body.onclick = () => {
console.log('body');
}
</script>
</html>
输出结果:
输出顺序: button > span > div > body > html > document
图片示例:
事件捕获
上一节点接收事件,然后向下传播到具体节点元素
举个栗子:
层级关系: document > html > body > div > span > button
<!DOCTYPE html>
<html>
<body>
<div id="div">
<span id="span">
<button id="button">
点击
</button>
</span>
</div>
</body>
<script>
const body = document.body;
const div = document.querySelector('div');
const span = document.querySelector('span');
const button = document.querySelector('button');
div.addEventListener('click', (event) => {
console.log('div');
}, true); // false 为冒泡事件、true为捕获事件
span.addEventListener('click', (event) => {
console.log('span');
}, true);
button.addEventListener('click', (event) => {
console.log('button');
}, true);
body.addEventListener('click', (event) => {
console.log('body');
}, true);
</script>
</html>
输出结果:
输出顺序: body > div > span > button
图片示例:
DOM事件流
事件先是从 捕获事件开始,再到目标事件,最后冒泡事件。
举个栗子:
<!DOCTYPE html>
<html>
<body>
<div id="div">
<button onclick="buttonClick()">
点击
</button>
</div>
</body>
<script>
const body = document.body;
const div = document.querySelector('div');
const button = document.querySelector('button');
const buttonClick = (event) => {
console.log('button');
}; // 目标事件
div.addEventListener('click', (event) => {
console.log('div');
}, false); // 冒泡事件
body.addEventListener('click', (event) => {
console.log('body');
}, true); // 捕获事件
</script>
</html>
输出结果:
输出顺序:捕获事件 > 目标事件 > 冒泡事件
图片示例:
阻止事件冒泡
w3c模型:调用事件的event.stopPropagation()方法
微软的模型: 设置事件的cancelBubble的属性为true
document.body.addEventListener('click', (event) => {
if(event){
event.stopPropagation();
}else{
window.event.cancelBubble = true;
}
}, false);
// React框架阻止冒泡的方法
const click = (event)=>{
event.nativeEvent.stopImmediatePropagation();
}
举个栗子:
<!DOCTYPE html>
<html>
<body>
<div id="div">
<button id="button">
点击
</button>
</div>
</body>
<script>
const body = document.body;
const div = document.querySelector('div');
const button = document.querySelector('button');
button.addEventListener('click', (event) => {
console.log('button');
if(event){
event.stopPropagation();
}else{
window.event.cancelBubble = true;
}
}, false);
div.addEventListener('click', (event) => {
console.log('div');
}, false);
body.addEventListener('click', (event) => {
console.log('body');
}, false);
</script>
</html>
输出结果: