美文网首页
32-进阶:DOM事件

32-进阶:DOM事件

作者: 格林姆大师 | 来源:发表于2018-07-29 23:58 被阅读0次

    上个图复习一下:


    image.png

    1. 点击别处关闭图层

    html:

    <body>
        <div id="wrapper" class="wrapper">
            <button id="clickMe" >点我</button>
            <div id="popover" class="popover">浮层</div>
        </div>
    </body>
    

    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的方案:

    <!DOCTYPE html>
    <html lang="zh-Hans">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <link rel="stylesheet" href="./style.css">
        <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
    </head>
    <body>
        <div id="wrapper" class="wrapper">
            <button id="clickMe" >点我</button>
            <div id="popover" class="popover">
                <input type="checkbox">浮层
            </div>
        </div>
    </body>
    <script src="main.js"></script>
    </html>
    
    $(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)----既阻止默认事件,又阻止事件传播;
    阻止默认事件 会引起一个问题---<input type="checkbox">无法被选中;因此,是使用阻止默认事件是得注意范围;
    改为:

    $(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
    

    测试:

    <!DOCTYPE html>
    <html>
    <head>
    <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
      <meta charset="utf-8">
      <title>JS Bin</title>
    </head>
    <body>
    <div class="red">
      <div class="blue">
        <div class="green">
          <div class="yellow">
            <div class="orange">
              <div class="purple"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    </body>
    </html>
    
    *{
      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事件

          本文链接:https://www.haomeiwen.com/subject/fqlymftx.html