点击别处关闭浮层

DOM事件模型进来了解下~

需求:点击button出现浮层,点击别处关闭浮层。
我们有一个按钮和一个浮层,浮层内为一个checkbox,浮层默认不显示:

1
2
3
4
5
6
<div id="wrapper" class="wrapper">
<button id="clickMe">点我</button>
<div id="popover" class="popover">
<input type="checkbox">浮层
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.wrapper{
position: relative;
display: inline-block;
}
.popover{
position: absolute;
border: 1px solid red;
padding: 10px;
margin-left: 1px;
left: 100%;
top: 0;
white-space: nowrap;
background: white;
display: none;
}

方案一: 监听button和document,button被点击时浮层显示,document除button和浮层以外的地方被点击是,浮层隐藏。

1
2
3
4
5
6
7
8
9
clickMe.addEventListener('click', function(){
popover.style.display = 'block'
})
wrapper.addEventListener('click', function(e){
e.stopPropagation()
}) //阻止冒泡
document.addEventListener('click', function(){
popover.style.display = 'none'
})
  • 阻止冒泡:在冒泡阶段执行函数,即先执行clickMe中的函数,给浮层添加block,如果不阻止冒泡,会继续向上,到document中时再执行其中的函数,使浮层又变为display: none;
  • 监听document或监听html都是可以的,(document.documentElement.addEventListener()),但是如果监听body要注意body的高度。
  • 每次点击document都会被监听,浪费内存。

方案二: 用jQuery 只有在浮层显示的时候监听一次document。

1
2
3
4
5
6
7
8
9
10
$(clickMe).on('click', function(){
$(popover).show()
console.log('block')
$(document).one('click', function(){
$(popover).hide()
}) //只在浮层show的时候监听一次document
})
$(wrapper).on('click', function(e){
e.stopPropagation()
})
  • 只有在浮层show的时候监听一次document,也就是:点击button,浮层显示 => 监听document => 点击别处,浮层隐藏 => 不再监听document,节省内存;
  • 注意不能写成$(wrapper).on('click', false),因为这样写会同时阻止冒泡和阻止默认事件,导致checkbox无法选中。