深度理解DOM事件(实例)

前言

通过如下两个实例来理解DOM事件

  1. 实例1--点击别处关闭浮层
  2. onclick与addEventListener的区别

  3. 实例2--点击后颜色一层一个层出现的漂亮的彩虹圈

1  实例1--点击别处关闭浮层

  • 代码效果演示:原生JSjQuery
  • HTML代码
      <div id="wrapper" class="wrapper">
        <button id="clickMe">点我</button>
        <div id="popover" class="popover">
          <input type="checkbox">浮层
        </div>
      </div>

     

  • CSS代码
    .wrapper{
      display:inline-block;
      position: relative;
    }
    
    .popover{
      display: none;
      border: 1px orange solid;
      top: 0px;
      /*宽度是上级元素的100%*/
      left: 130%;
      padding: 8px;
      border-radius: 4px;
      position: absolute;
      background: white;
      /*规定段落中的文本不进行换行*/
      white-space: nowrap;
      
    }
    /*画浮层左边的小指向箭头*/
    .popover::before{
      position: absolute;
      right: 100%;
      top: 4px;
      border: 10px solid transparent;
      border-right-color: orange;
      content: '';
    }
    .popover::after{
      position: absolute;
      right: 100%;
      top: 4px;
      border: 10px solid transparent;
      border-right-color: white;
      content: '';
      margin-right: -1px;
    }

     

  • JS代码-原生js 
    /*点击按钮触发浮层*/
    clickMe.addEventListener('click', function(){
      popover.style.display = 'block'
    })
    /*阻止默认事件*/
    wrapper.addEventListener('click', function(e){
       e.stopPropagation()
     })
    /*点击任意处关闭浮层*/
    document.addEventListener('click', function(){
      popover.style.display = 'none'
    })

     

  • JS代码-jQuery
    $(clickMe).on('click',function(){
      $(popover).show()
      /*如果不加定时器会同步执行show()和hide(),即看起来什么都没有发生*/
      setTimeout(function(){
         $(document).one('click', function() {
           $(popover).hide()
         })
      },0)
    })

     

2  onclick与addEventListener的区别

  • 实例1使用的原生JS,为什么使用addEventListener(),而不使用onclick() --onclick()只能添加一个事件,多个事件时只会输出最后一个,而实例1中存在多个事件,不能用onclick()
  • onclick与addEventListener实际上可分为:Inline events与Event Listeners
  • Event Listeners (“addEventListener” and “IE's attachEvent”)
    • 两者相同点:都是时间监听器。
    • 两者不同点:
      • addEventListener:很多浏览器支持addEventListener(IE9、IE10、IE11、chrome、firefox、opera、safari支持),使用方式如下:
        //addEventListener接受三个参数,最后一个参数默认是false。(false表示事件处理将在冒泡阶段执行,true表示事件处理将在捕获阶段执行)
        //addEventListener(type,listener,options) 
        var target = document.getElementById("test");
        target.addEventListener('click',function test(){
                console.log("Hi");
        },false)
      • attachEvent:IE中提供的类似addEventListener的事件监听器,使用方式如下:
        //qqq
        var target = document.getElementById("test");
        target.attachEvent('onclick',test);
        function test(){
             console.log("Hi");
        }
      • 理论上,Event Listeners (addEventListener and IE's attachEvent)可以无限增加事件监听给某个一元素。实际应用的约束就是客户端内存的限制,这一点因每个浏览器而异
        var target = document.getElementById("test");
        target.addEventListener('click',function test(){
                console.log("Hi");
        },false)
        target.addEventListener('click',function test(){
                console.log("Hello");
        },false)
        //Hi
        //Hello

         

  •  Inline events (“HTML onclick="" property” and “element.onclick”)
    • 使用方式:
      • onclick=""    
        <a id="test" href="#" onclick="function()">clickMe</a>
      • element.onclick      
        <a id="test" href="#">clickMe</a>
         
        var target = document.getElementById('test')
        target.onclick = function(){
            console.log('Hi');
        }

         

      • Inline events只能添加一个事件,如果同时有多个,只会输出最后一个的结果   
        var target = document.getElementById('tttt')
        target.onclick = function(){
            console.log('Hi');
        }
        target.onclick = function(){
            console.log('Hello');
        }
        //Hello

         

  • Inline events与Event Listeners的区别:Event Listeners可以添加无数个(理论上)事件,Inline events只能添加1个事件,且下面的会覆盖上面的。
 

3  实例2--点击后颜色一层一个层出现的漂亮的彩虹圈

  • 代码效果:彩虹圈
  • HTML代码
    <div class="red">
      <div class="blue">
        <div class="green">
          <div class="yellow">
            <div class="orange">
              <div class="purple">
                
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  • CSS代码
    *{margin:0;padding:0;box-sizing:border-box;}
    
    //设置背景颜色
    .red.active { background: red; }
    .blue.active { background: blue; }
    .green.active { background: green; }
    .yellow.active { background: yellow; }
    .orange.active { background: orange; }
    .purple.active { background: purple; }
    
    //设置一层一层圆圈以及动画过渡事件
    div {
      border: 1px solid black;
      padding: 10px;
      transition: all 0.5s;
      display: flex;
      flex:1;
      border-radius: 50%;
      background: white;
    }
    
    //设置最外圈的长宽
    .red{ width: 100vw; height: 100vw; }

     

  • JS代码
    let divs = $('div').get()
    let n = 0
    
    for (let i = 0; i < divs.length; i++) {
       //addEventListener()最后一个参数为true
       //即执行捕获阶段--从外层到里层,即从爷爷到儿子
      divs[i].addEventListener('click', function() {
        setTimeout(function() {
          divs[i].classList.add('active')
        }, n * 500)
        n += 1
      }, true)
    }
    
    for (let i = 0; i < divs.length; i++) {
       //addEventListener()最后一个参数为false
       //即执行冒泡阶段--从里层到外层,即从儿子到爷爷
      divs[i].addEventListener('click', function() {
        setTimeout(function() {
          divs[i].classList.remove('active')
        }, n * 500)
        n += 1
      }, false)
    }
    
    //⚠️有一个特殊情况:即如果都是自己身上同时捕获(true)和冒泡(false),此时执行顺序和捕获(true)和冒泡(false)无关,谁在前面就先执行哪个

     

     

 

posted @ 2018-06-01 20:44  Nola  阅读(351)  评论(0编辑  收藏  举报