32-进阶:DOM事件

上个图复习一下:


image.png

1. 点击别处关闭图层

html:


    
浮层

css:

.wrapper{
    border: 1px solid red;
    position: relative;
    display: inline-block;
  }
  .popover{
    border: 1px solid black;
    position: absolute;
    left: 100%;
    white-space: nowrap;
    top: 0;
    margin-left: 20px;
    padding: 10px;
  }
  .popover::before{
    content: '';
    border: 10px solid transparent;
    border-right-color: black;
    position: absolute;
    right: 100%;
    top: 0;
  }
  .popover::after{
    content: '';
    border: 10px solid transparent;
    border-right-color: white;
    position: absolute;
    right: 100%;
    top: 0;
    margin-left: 100px;  /* 问题1: 此句无任何效果??? */
    margin-right: -1px;
  }

js思路:


js版本1.0:

clickMe.addEventListener('click',function(){
  popover.style.display = 'block'
})
document.body.addEventListener('click',function(){
  popover.style.display = 'none'
  console.log(1)
})

document.body.addEventListener-将外部区域事件添加到body上。
问题:body的高度有内部文档流的高度总和决定,实际点击时有问题。


js版本1.1:

//将外部区域事件添加到document上
document.addEventListener('click',function(){
    popover.style.display = 'none'
    console.log(2)
})

//将外部区域事件添加到html上
document.documentElement.addEventListener('click',function(){
    popover.style.display = 'none'
    console.log(3)
})

将外部区域事件添加到document和html上能达到点击外部区域的要求;
问题:实际点击 clickMe 浮层并没有出现;
采用debugger调试法,如下:

clickMe.addEventListener('click',function(){
    popover.style.display = 'block'
    debugger
  })
document.addEventListener('click',function(){
    popover.style.display = 'none'
    console.log(2)
})

事件过程见下图:


image.png

js版本2.0---阻止事件冒泡:

clickMe.addEventListener('click',function(e){
    popover.style.display = 'block'
    e.stopPropagation()
  })

document.addEventListener('click',function(){
    popover.style.display = 'none'
    console.log(2)
})

event.stopPropagation()---阻止捕获和冒泡阶段中当前事件的进一步传播;
此版本在功能上基本达到要求;
问题:点击 浮层 元素时 浮层也会消失???
改进:

clickMe.addEventListener('click',function(e){
    popover.style.display = 'block'
})
wrapper.addEventListener('click',function(e){
    e.stopPropagation()
})

document.addEventListener('click',function(){
    popover.style.display = 'none'
    console.log(2)
})

将event.stopPropagation() 添加在 元素wrapper 上;
上述改进方案基本实现了要求,不过还有点问题‘
问题:document 上每添加一个事件,都要好用一点内存,如果document 上的事件很多,会严重耗费资源。。。。。。


js版本3.0---jQuery的方案:




    
    
    
    Document
    
    


    
浮层
$(clickMe).on('click',function(){
    $(popover).show()
})

$(wrapper).on('click',false)
// 等价于---
// $(wrapper).on('click',function(e){
//     e.preventDefault()
//     e.stopPropagation()
// })

$(document).on('click',function(){
    $(popover).hide()
})

以上采用jQuery重新实现2.0版本,
$(wrapper).on('click',false)----既阻止默认事件,又阻止事件传播;
阻止默认事件 会引起一个问题---无法被选中;因此,是使用阻止默认事件是得注意范围;
改为:

$(wrapper).on('click',function(e){
    e.stopPropagation()
})

js版本4.0---节省内存资源:

$(clickMe).on('click',function(){
    $(popover).show()
    $(document).one('click',function(){
        $(popover).hide()
    })
})

$(wrapper).on('click',function(e){
    e.stopPropagation()
})

$(document).one('click',function(){})----只监听一次;
以上只在点击 clickMe元素 后才开始监听一次 document 点击,完成一次监听后就清理了,这样就能少占用资源了;


js版本4.1---节省内存资源---优化尝试:

$(clickMe).on('click',function(){
    $(popover).show()
    $(document).one('click',function(){
        $(popover).hide()
    })
})

省去阻止冒泡事件后发现,点击 clickMe 浮层并没有出现????
测试:

$(clickMe).on('click',function(){
    $(popover).show()
    console.log('show')
    $(document).one('click',function(){
        console.log('我觉得点击clickMe时,这里应该不会执行')
        console.log('hide')
        $(popover).hide()
    })
})

测试结果:第一次点击 clickMe 时,$(popover).hide() 就已经执行了????
图解如下:

image.png

解决方法:1-添加阻止冒泡事件;2-设定一个定时器来延时(改变执行次序)
方法2如下:

$(clickMe).on('click',function(){
    $(popover).show()
    console.log('show')
    setTimeout(function(){
        $(document).one('click',function(){
            console.log('我觉得点击clickMe时,这里应该不会执行')
            console.log('hide')
            $(popover).hide()
        })
    },0)
})

注意上述 setTimeout 中的事件设定为0ms,但是,依然可以达到改变执行时序的效果,也就是说,setTimeout 会在当前的代码执行完后才开始计算延时时间;
测试:


结果:

//点击clickMe时
show
点击clickMe事件走到了document
添加 one click
点击clickMe事件走到了document

//点击document时
我觉得点击clickMe时,这里应该不会执行
hide

测试:





  
  JS Bin


*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
div{
  padding: 20px;
  border: 1px solid black;
  /* border-radius: 50%; */
  transition: all 0.5s;
  display: flex;
  flex: 1;
}
.red{
  width: 100vw;
  height: 100vw;
}
.red.active{
  background-color: red;
}
.blue.active{
  background-color: blue;
}
.green.active{
  background-color: green;
}
.yellow.active{
  background-color: yellow;
}
.orange.active{
  background-color: orange;
}
.purple.active{
  background-color: purple;
}
var n=0
$('div').on('click',function(e){
  setTimeout(function(){
    $(e.currentTarget).addClass('active')
    console.log(n)
  },n*500)
  n=n+1
})

你可能感兴趣的:(32-进阶:DOM事件)