10/6
2020
假设有一个页面,上面黄色部分是一个浮窗。我们需要用 JavaScript 实现:点击页面其他部分时关闭这个浮窗。
要点在于区分用户点击的是浮窗还是其他部分。
假设我们将浮窗的元素保存为变量 a,那么如下代码即可实现此效果:
a.addEventListener('click', (e) => { const ev = e || window.event ev.stopPropagation() }) document.addEventListener('click', () => { a.style.display === 'none' })
做了两件事:
- 点击浮窗时(包括点击浮窗内的元素),阻止事件冒泡;
- 点击 document 时,隐藏浮窗。
为什么这样可以区分点击了哪里呢?因为达到了这样的效果:
- 点击浮窗时,不会触发 document 的点击事件;
- 点击浮窗之外的元素,才会触发 document 的点击事件。
这涉及到 JavaScript 的事件触发机制。如果有没想明白的同学可以继续往下看。
当一个事件发生时,塔首先会进入捕获阶段(Event Capturing),自外部向内部传播。传播到最内部之后,再进入冒泡阶段(Event Bubbling),向外部传播:
上面代码中监听事件都是监听的冒泡部分,所以我们只看冒泡部分:
当点击浮窗时,我们阻断了冒泡的传播:
所以此时不会传播到 document 上,在 document 上也监听不到这个事件。
当点击浮窗之外的元素时,由于我们没有阻断事件的传播,所以事件会冒泡到 document 上,被监听到:
所以最后的效果就是,当你在 document 上监听到点击事件时,一定是浮窗之外的元素触发的。此时就可以关闭这浮窗了。