美文网首页
事件的冒泡捕获阻止默认代理

事件的冒泡捕获阻止默认代理

作者: 流着万条永远的河 | 来源:发表于2017-09-15 17:15 被阅读0次

    事件的认识

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <button id="btn">click me</button>
    <script>
    var btn= document.querySelector('#btn')
    btn.onclick = function(e){
      console.log(e)
    }                    //e代表绑定的事件对象,运行可得到,是形参而已。
    </script>
    </body>
    </html>
    //得到事件——对象 MouseEvent {isTrusted: true, screenX: 594, screenY: 87, clientX: 37, clientY: 21…}
    altKey: false    //点时没有按alt键
    bubbles: true      //冒泡的
    button: 0
    buttons: 0
    cancelBubble: false
    cancelable: true
    clientX: 37                      //位置
    clientY: 21                //位置
    composed: true
    ctrlKey: false
    currentTarget: null
    defaultPrevented: false
    detail: 1
    eventPhase: 0
    fromElement: null
    isTrusted: true
    layerX: 37
    layerY: 21
    metaKey: false
    movementX: 0
    movementY: 0
    offsetX: 28                 //点击时鼠标 相对于元素本身的偏移
    offsetY: 9             //点击时相对于元素本身的偏移
    pageX: 37
    pageY: 21
    path: Array(5)relatedTarget: null
    returnValue: true
    screenX: 594
    screenY: 87
    shiftKey: false
    sourceCapabilities: InputDeviceCapabilities
    srcElement: button#btn
    target: button#btn                            //通过e.target看看点的是谁,等同于this和btn,但是有时候会有区别的。
    timeStamp: 14919.125000000002
    toElement: button#btn
    type: "click"
    view: Window
    which: 1
    x: 37
    y: 21
    __proto__: MouseEvent
    

    removeEventListener解绑事件的,其中第二个参数也就是函数不能是匿名函数,否则解绑不了的,同理于addEventListener。

    IE兼容

    IE有:

    • attachEvent添加
    • detachEvent删除
      全都默认冒泡模式,两个参数,而且事件是'onclick',对比于addEventListener的'click'。这时候,this不是绑定的元素了,而是window对象。

    事件对象

    刚开始的例子已经得到了事件的对象了,这里比较重要的几个拿出来说说:

    • target 事件的目标元素
    • stopPropagation() 取消事件的进一步捕获或者冒泡,就是中断。
    • preventDefault() 取消事件的默认行为:a链接点击跳转;form表单里的按钮type=submit,点击就会提交,,,先不让它们跳转,提交,先做一些事情,然后才完成默认的。
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    <style>
    .container,
    .box,
    .target{
      border:1px solid;
      padding:20px;
    }
    </style>
    </head>
    <body>
    <button id="btn">click me</button>
    <div class="container">
      container
      <div class="box">
        box
        <div class="target">
          target
        </div>
      </div>
    </div>
    <script>
    var btn= document.querySelector('#btn')
    btn.onclick = function(e){
      console.log(e)
    }
    document.querySelector('.container').addEventListener('click',function(e){
    console.log('container click..in捕获')  
    },true)
    document.querySelector('.box').addEventListener('click',function(e){
    console.log('box click..in捕获')  
    },true)
    document.querySelector('.target').addEventListener('click',function(e){
    console.log('target click..in捕获')  
    },true)
    document.querySelector('.container').addEventListener('click',function(e){
    console.log('container click..in冒泡')  
    },false)
    document.querySelector('.box').addEventListener('click',function(e){
     // e.stopPropagation()
      console.log('box click..in冒泡')  
    },false)
    document.querySelector('.target').addEventListener('click',function(e){
    console.log('target click..in冒泡')  
    },false)
    </script>
      </body>
    </html>
    //"container click..in捕获"
    "box click..in捕获"
    "target click..in捕获"
    "target click..in冒泡"
    "box click..in冒泡"
    "container click..in冒泡"
    
    //在box中加入stopPropagation()然后,,,
    "container click..in捕获"
    "box click..in捕获"
    "target click..in捕获"
    "target click..in冒泡"
    "box click..in冒泡"
    stopPropagation()会阻止事件向后传递,向后而已,当下没事。
    
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <a href="http://baidu.com">baidu</a>
    <script>
    document.querySelector('a').onclick = 
      function(e){
      e.preventDefault()                   //先不跳转
      console.log(this.href)
      if(/baidu.com/.test(this.href)){        //是否包含baidu.com
        location.href = this.href            //跳转
      }
    }
    </script>
    </body>
    </html>
    

    老的IE里的事件获取

    用window.event获取,比较奇葩。

    常见事件

    • load
    • unload
    • select
    • changge
    • submit
    • resize
    • scroll
    • focus
    • blur

    事件代理

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <div class="container">
      <div class="box">box1</div>
       <div class="box">box2</div>
    </div>
    <script>
    function $(selector){
      return document.querySelector(selector)
    }
    function $$(selector){
      return document.querySelectorAll(selector)
    }
    $('.box').onclick = function(){
      console.log(this.innerText)
    }
    //$$('.box').onclick = function(){
    //  console.log(this.innerText)
    //}          //先不用
    </script>
    </body>
    </html>
    //点击元素出现文本信息,只是选择了box1,box2没有选择。
    用$$,反而点击两个都没有输出文本,为什么?
    在控制台:
    $$('.box')
    (2) [div.box, div.box]    //选中了,是个NodeList类数组对象
    $$('.box').onclick
    undefined                  //没有onclick这个事件!事件只能一个一个去绑定。
    
    如图

    这里没有addEventListener和onclick的,不过有forEach。

    $$('.box').forEach(function(node){
      node.onclick=function(){
        console.log(node.innerText)
      }
    })
    //就可以了,先遍历,然后再写。
    

    比较麻烦,能不能绑定在父元素上?

    $('.container').onclick=function(e){
      if(e.target.classList.contains('box')){
        console.log(e.target.innerText)
      }
    }            //e还是形参,事件发生时才会有意义有值,也就是点击的瞬间,其他时候,是会报错的,没有值的。
    

    再深一步:forEach不一定是万能的,,,

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <div class="container">
      <div class="box">box1</div>
       <div class="box">box2</div> 
    </div>
      <button id="add">add</button>
    <script>
    function $(selector){
      return document.querySelector(selector)
    }
    function $$(selector){
      return document.querySelectorAll(selector)
    }
    $$('.box').onclick = function(){
      console.log(this.innerText)
    }
    $$('.box').forEach(function(node){
     node.onclick=function(){
       console.log(node.innerText)
      }
    })
    var i =3
    $('#add').onclick=function(){
      var box =document.createElement('div')
      box.classList.add('box')
      box.innerText = 'box' +(i++)
      $('.container').appendChild(box)
    }
    </script>
    </body>
    </html>
    //这时候add是可以正常输出bix3,box4,box5,,,,,,,
    但是控制台输出的innerText就还是原来是box1,box2,没有后来增加的了。
    因为forEach一开始只给原本就有的做了遍历,都绑定了事件,后面新增的对象没有绑定啊。
    

    代理模式下呢:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
    <div class="container">
      <div class="box">box1</div>
       <div class="box">box2</div> 
    </div>
      <button id="add">add</button>
    <script>
    function $(selector){
      return document.querySelector(selector)
    }
    function $$(selector){
      return document.querySelectorAll(selector)
    }
    $$('.box').onclick = function(){
      console.log(this.innerText)
    }
    $('.container').onclick=function(e){
      if(e.target.classList.contains('box')){
        console.log(e.target.innerText)
      }
    }                   //代理模式
    var i =3
    $('#add').onclick=function(){
      var box =document.createElement('div')
      box.classList.add('box')
      box.innerText = 'box' +(i++)
      $('.container').appendChild(box)
    }
    </script>
    </body>
    </html>
    可正常跟进子元素的变化,同步绑定事件了。没有绑定事件,但是都会向父元素冒泡,父元素绑定了事件啊
    

    事件代理很好,不需要重新绑定事件了,尤其是懒加载啊,或者是子元素会发生变化啊。

    相关文章

      网友评论

          本文标题:事件的冒泡捕获阻止默认代理

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