触发 / 关闭浮层

2019-05-15  本文已影响0人  养乐多__

实现功能:点击按钮触发浮层,点击别处关闭浮层。

<div id="wrapper" class="wrapper">
  <button id="clickMe">点击</button>
  <div id="popover" class="popover">
    <input type="checkbox">浮层
  </div>
</div>
.popover{
  display: none;
}

1. 方案一 --- 用 DOM Events 实现

  1. 如上,浮层的样式默认为“不显示 ”。我们监听 button 点击事件,使 button 被点击时显示浮层。
clickMe.addEventListener('click', function(){
  popover.style.display = 'block'
})
  1. 实现点别处关闭浮层时,可以监听 document
    注意:不要监听 body,因为 body 是被文档流撑起来的,高度很小,空白处可能取不到 body
document.addEventListener('click', function(){
  popover.style.display = 'none'
})
  1. 因为点击 buttonpopoverdocument 也会被点击,导致无法触发浮层。所以要在它们的父元素 wrapper阻断冒泡
wrapper.addEventListener('click', function(e){
  e.stopPropagation() //停止传播,阻断冒泡
})

2. 方案二 --- 用 jQuery 实现

  1. 同理,我们改为 jQuery 语句:
$(clickMe).on('click', function(){
  $(popover).show()
})
$(wrapper).on('click', function(e){
  e.stopPropagation()
})
$(document).on('click', function(){
  $(popover).hide()
})
  1. 同时阻止传播和阻止默认事件
    jQuery 提供了一个方便的写法,用 false 可以同时阻止传播和阻止默认事件。但此处不可以用,因为会导致无法勾选 checkbox(默认它的动作被阻止)而出现 bug。
$(wrapper).on('click', false)  //同时阻止传播和阻止默认事件
// 等价于
$(wrapper).on('click', function(e){
  e.preventDefalt()
  e.stopPropagation()
})

所以我么平时使用 preventDefault 时一般不要直接放在 div 上。

  1. 节省内存
    document 处于一直被监听的状态,非常浪费内存。为了节省内存,我们可以使它只在浮层出现的时候被监听一次。
$(clickMe).on('click', function(){
  $(popover).show()
  $(document).one('click', function(){ // 只在 button 被点击时监听 document 
    $(popover).hide()
  })
})
$(wrapper).on('click', function(e){
  e.stopPropagation()
})
3. 完善功能

为使浮层更具实用性,我们使其最终实现的功能包括:

为了更好地学习理解 DOM Events,选择用方案一来实现:

clickMe.addEventListener('click',function(e){
    if(popover.style.display === 'none'){ // 若浮层在关闭状态
        popover.style.display = 'block' // 显示浮层
        e.stopPropagation()  // 阻止冒泡
    }else{
        popover.style.display = 'none' // 否则关闭浮层
    }
})
document.addEventListener('click',function(){
        popover.style.display = 'none'
    })
popover.addEventListener('click',function(e){
    e.stopPropagation() 
})

但是在调试时发现存在 bug:运行代码后首次点击 button 并不会触发浮层。
后来发现,因为我直接在 js 中用 style 去控制样式,而它是直接去获取元素上的 style 属性的,因此之前写在 css 里的 display 属性它获取不到(除非用 window.getComputedStyle 去获取),首次点击按钮时 display 相当于是空字符串。

4. 优化代码

首先在 css 中添加一个类 show 来显示浮层:

.show{
  display: block;
}

完整的 js 代码:

clickMe.addEventListener('click', function(e) {
  let p1 = document.getElementById('popover')
  if (!p1.classList.contains('show')) { // 判断当前类是否包含 show 
    p1.classList.add('show')
    e.stopPropagation() // 停止传播,阻断冒泡
  } else {
    p1.classList.remove('show')
  }
  document.addEventListener('click', function() {
    p1.classList.remove('show')
  })
})
popover.addEventListener('click', function(e) {
  e.stopPropagation()
})
上一篇下一篇

猜你喜欢

热点阅读