码迷,mamicode.com
首页 > 其他好文 > 详细

事件流 事件冒泡和事件捕获

时间:2019-06-19 22:07:52      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:有关   获取   use   事件对象   也会   rdl   script   evo   targe   

事件冒泡和事件捕获

他们是描述事件触发时序问题的术语。

DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从外部到内部。 
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从内部到外部

事件冒泡

<body>
  <div class="parent">
    <div class="son">
      <div class="grandson"></div>
    </div>

  </div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    $(.parent).click(function(){
      console.log()                    
    })
    $(.son).click(function(){
      console.log()
    })
    $(.grandson).click(function(){
      console.log(孙子)
    })
  </script>
</body>
</html>

事件冒泡 父子都绑定了事件,点击子元素,会触发子元素绑定的事件;同时也会触发父元素绑定的事件

    // 当点击 parent不与son grandson相交区域              打印结果为  父
    // 当点击 parent与son相交 而不与grandson相交区域       打印结果为  子-父
    // 当点击 parent  son grandson 三者相交区域           打印结果为  孙子-子-父
    // 这是因为 事件的触发顺序自内向外,这就是事件冒泡。
    
    // 若是在grandson 加上阻止事件冒泡
    // $(‘.grandson‘).click(function(e){
    //   console.log(‘孙子‘)
    //   e.stopPropagation()
    // })
    // 此时当点击 parent  son grandson 三者相交区域        打印结果为  孙子
    // 因为 e.stopPropagation() 阻止了冒泡向 son grandson 触发事件

 由于一些人会以为显示出来儿子在父亲里面的时候,自然点了儿子相当于点了父亲,所以这个例子我故意把两个盒子绝对定位在了两个不同的位置,所以点击事件给页面显示出来的位置是没关系的,而是跟html代码中的位置有关系。

使用绝对定位,把parent、son、grandson分别定位到互不重叠的地区,点击grandson       打印的结果依然为孙子-子-父

<body>
  <div class="parent" id="parent">
    <div class="son" id="son">
      <div class="grandson" id="grandson"></div>
    </div>

  </div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    
    // var parent = document.getElementsByClassName(‘parent‘)
    // var son=document.getElementsByClassName(‘son‘)
    // var grandson=document.getElementsByClassName(‘grandson‘)

    var parent = document.getElementById(‘parent‘)
    var son=document.getElementById(‘son‘)
    var grandson=document.getElementById(‘grandson‘)

    parent.addEventListener(‘click‘,function(){
      console.log(‘父‘)  
    },false)
    son.addEventListener(‘click‘,function(){
      console.log(‘子‘)  
    },false)
    grandson.addEventListener(‘click‘,function(){
      console.log(‘孙子‘)  
    },false)
  </script>
</body>

使用事件监听  默认为false是事件冒泡和jquey onclick一样也是默认事件冒泡      

点击 grandson时,打印结果 孙子-子-父

注意:

    var parent1 = document.getElementsByClassName(‘parent‘)
    console.log(parent1)
    // 打印结果:HTMLCollection [div#parent.parent, parent: div#parent.parent]

    var parent2 = document.getElementById(‘parent‘)
    console.log(parent2)
    // 打印结果:<div class=‘parent‘ id=‘parent‘>...</div>

 

    parent1.addEventListener(‘click‘,function(){
      console.log(‘结果1‘)  
    },false)
    // 结果报错 Uncaught TypeError: parent1.addEventListener is not a function


    parent2.addEventListener(‘click‘,function(){
      console.log(‘结果2‘)  
    },false)
    //使用getElementById能正确打印出结果2

 

使用jquey 和js 获取元素的不同

  <script>
    var parentid=$(‘#parent‘)
    console.log(parentid)
    // 打印结果 r.fn.init [div#parent.parent]

var parentclass=$(‘.parent‘) console.log(parentclass) // 打印结果 r.fn.init [div#parent.parent, prevObject: r.fn.init(1)]

var parent_js_id=document.getElementById(‘parent‘) console.log(parent_js_id) // 打印结果 <div class="parent" id="parent">....</div>

var parent_js_class=document.getElementsByClassName(‘parent‘) console.log(parent_js_class) // 打印结果 HTMLCollection [div#parent.parent, parent: div#parent.parent] </script>

 

事件捕获

  <script>
    var parent = document.getElementById(‘parent‘)
    var son=document.getElementById(‘son‘)
    var grandson=document.getElementById(‘grandson‘)

    parent.addEventListener(‘click‘,function(){
      console.log(‘父‘)  
    },true)
    son.addEventListener(‘click‘,function(){
      console.log(‘子‘)  
    },true)
    grandson.addEventListener(‘click‘,function(){
      console.log(‘孙子‘)  

    },true)
    
    // 改为true时 ,使用的是事件捕获 由外向内   
    // 点击  parent 时               打印结果 父
    // 点击  son 时                  打印结果 父-子
    // 点击  grandson时              打印结果 父-子-孙子
    
    // 也能使用e.stopPropagation() 
    // parent.addEventListener(‘click‘,function(){
    //   console.log(‘父‘)  
    // },true)
    // son.addEventListener(‘click‘,function(e){
    //   console.log(‘子‘)  
    //   e.stopPropagation()
    // },true)
    // grandson.addEventListener(‘click‘,function(){
    //   console.log(‘孙子‘)  

    // },true)
    // 当点击 grandson时  不使用stopPropagation()    打印结果 父-子-孙子
    // 当点击 grandson时  使用stopPropagation()      打印结果 父-子
  </script>

 

return false

javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。

<body>
  <div class="parent" id="parent">
    <div class="son" id="son">
      <div class="grandson" id="grandson">
        <a id="click" href="https://baidu.com">点击</a>
      </div>
    </div>

  </div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    $(‘.parent‘).click(function(){
      console.log(‘父‘)                    
    })
    $(‘.son‘).click(function(){
      console.log(‘子‘)
    })
    $(‘.grandson‘).click(function(){
      console.log(‘孙子‘)
    })
    // jq
    $(‘#click‘).click(function(){
      console.log(‘jq点击‘)
      // 在jq中使用 return false  即阻止默认行为,又阻止冒泡
      return false
    })
  //和上面同样效果
// $(‘#click‘).on(‘click‘,function(){ // console.log(‘点击‘) 打印结果 点击-孙子-子-父 不会执行a标签的跳转 // return false // }) // js var a=document.getElementById(‘click‘) a.onclick=function(){ console.log(‘点击‘) return false //打印结果 点击-孙子-子-父 不会执行a标签的跳转 } // document.getElementById(‘click‘).addEventListener(‘click‘,function(){ // console.log(‘点击‘) // return false //打印结果 return false不执行 ????? // }) </script>

 

兼容不同浏览器的阻止事件冒泡和阻止默认行为

阻止事件冒泡

function stopBubble(e) { 
//如果提供了事件对象,则这是一个非IE浏览器 
if ( e && e.stopPropagation ) 
    //因此它支持W3C的stopPropagation()方法 
    e.stopPropagation(); 
else 
    //否则,我们需要使用IE的方式来取消事件冒泡 
    window.event.cancelBubble = true; 
}

 

阻止事件默认行为

//阻止浏览器的默认行为 
function stopDefault( e ) { 
    //阻止默认浏览器动作(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函数器默认动作的方式 
    else 
        window.event.returnValue = false; 
    return false; 
}

 preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type=”submit”>等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。

 

事件注意点

  1. event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等;
  2. event对象只在事件发生的过程中才有效。

firefox里的event跟IE里的不同,IE里的是全局变量,随时可用;firefox里的要用参数引导才能用,是运行时的临时变量。
在IE/Opera中是window.event,在Firefox中是event;而事件的对象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中两者都可用。

下面两句效果相同:

function a(e){
    var e = (e) ? e : ((window.event) ? window.event : null); 
    var e = e || window.event; // firefox下window.event为null, IE下event为null
}

由于jq中已经封装好的代码,可以直接使用jq来兼容不同浏览器

 

绑定事件

事件绑定常用三种方法

1.嵌入到dom上

<body>
  <div onclick="btnOpen()">按钮</div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    function btnOpen(){
        alert(1)
    }
  </script>
</body>

 

ps 使用系统定义的关键字来为函数命名,无效。

<body>
  <div onclick="open()">按钮</div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    function open(){
        alert(1)
    }
  </script>
</body>

 

2.直接绑定 

<body>
  <div id="btn">按钮</div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    document.getElementById(btn).onclick(function(){
      console.log(点击)
    })
  </script>
</body>

 

3.事件监听

<body>
  <div id="btn">按钮</div>
  <script src="../report/js/jquery.min.js"></script>
  <script>
    document.getElementById(btn).addEventListener(click,function(){
      console.log(按钮)
    })
    
  </script>
</body>

 

    // addEventListener(event, function, useCapture)
    //  event 事件名      function 事件触发执行的函数   
    // useCapture 默认为false 事件在冒泡阶段执行    true 事件在捕获阶段执行

 

事件流 事件冒泡和事件捕获

标签:有关   获取   use   事件对象   也会   rdl   script   evo   targe   

原文地址:https://www.cnblogs.com/zjx304/p/10032329.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!