需求:点击button出现浮层,点击别处关闭浮层。
我们有一个按钮和一个浮层,浮层内为一个checkbox,浮层默认不显示:
<div id="wrapper" class="wrapper">
<button id="clickMe">点我</button>
<div id="popover" class="popover">
<input type="checkbox">浮层
</div>
</div>
.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和浮层以外的地方被点击是,浮层隐藏。
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。
$(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无法选中。