请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
当 html 元素彼此间存在“血亲关系”,即它们层层嵌套,那么,最里层的元素发起人机交互动作时,外层的任意一层都可以接收到这个事件。可以将层层嵌套的元素想象成俄罗斯套娃:你戳一下最里层的娃娃,它外面的每一个娃娃都可以依次感知到被戳了一下。这就是所谓的“冒泡”:事件被触发后从触发点外溢,这个事件就像涟漪一样被传输到存在“直系亲属”关系的所有元素,只要它们原意监听。
网页“直系关系”示意图谱:
window → document → html → body → div(或其他元素)
试看下面的代码,重点理解 html 代码:四个 div 盒子层层嵌套,它们是“四代同堂”的直系亲属关系——
<style>
.ttDiv { margin: auto; width: 40vw; aspect-ratio: 1 / 1; border: 1px solid gray; display: grid; place-items: center; position: relative; }
.ttDiv::after { content: attr(data-counter); position: absolute; left: 10px; top: 5px; }
.outer1 { width: 40vw; margin-top: 100px; }
.inner1 { width: 30vw; }
.inner2 { width: 20vw; }
.inner3 { width: 10vw; }
</style>
<div id="div1" class="ttDiv outer1" data-counter="0">
<div id="div2" class="ttDiv inner1" data-counter="0">
<div id="div3" class="ttDiv inner2" data-counter="0">
<div id="div4" class="ttDiv inner3" data-counter="0"></div>
</div>
</div>
</div>
<script>
// 点击计数器函数
const clicking = (element) => {
let counter = element.dataset.counter * 1 + 1;
element.dataset.counter = counter;
}
// 获取所有的 .ttDiv 盒子
const ttDivs = document.querySelectorAll('.ttDiv');
// 盒子被点击时触发计数
ttDivs.forEach(ttdiv => {
ttdiv.onclick = () => clicking(ttdiv);
});
</script>
这组代码为每一个 div 设置了::after伪元素,用以展示被点击的次数。JS 代码设计了一个计数器函数:元素如果被点击则计数器加 1,然后每一个 div 都监听点击事件,该事件如果被触发则执行计数器函数。
理解冒泡事件,可以点击代码栏右上角“预览”按钮进入预览页面,点击不同层级的 div 元素,观察计数器的变化。
如你所见:冒泡是从里往外发起。如果点击的不是最里层的,那么,不被点击的里层 div 计数器不会发生变化。
网页元素冒泡路径示意图:
divs(或其它元素)→ body → html → document → window
冒泡如果不人为阻止,它一直会往外冒,直至“直系亲属”的最后一个成员。换言之,上述“四代同堂”的 div 之外,如果还有其它的属于它们祖先的 div 或是其它容器盒子,都会接收到冒泡事件,直至DOM“族谱”的根(window对象)才会停止。
阻止冒泡指特定元素的事件私有化,不允许外层的“直系亲属”捕获相关事件。这时候,可以在特定元素的指定事件(例如点击事件)中加入 event.stopPropagation()(中断传播)加以实现。前面的代码示例,每一个 div 都有 id 标识符,JS 中的元素点击事件代码可以通过识别目标的 id,如果与指定点击事件要阻止冒泡的 div 的 id 相匹配就阻隔事件的冒泡行为。可以这样改进 div 的点击事件:
// 盒子被点击时触发计数,阻止 div4 的点击行为冒泡
ttDivs.forEach( ttdiv => {
ttdiv.onclick = (event) => {
if (event.target.id === 'div4') event.stopPropagation();
clicking(ttdiv);
}
});
这么一来,最里层的 div 被点击时,只有它自己的计数器发生变化,外层所有元素都不再能够捕获到点击事件。而其长辈 div 没有受到限制,它们的点击事件仍然会冒泡。
|