事件流 事件冒泡和事件捕获
Posted zjx304
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事件流 事件冒泡和事件捕获相关的知识,希望对你有一定的参考价值。
事件冒泡和事件捕获
他们是描述事件触发时序问题的术语。
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也是不会起作用的。
事件注意点
- event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等;
- 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 事件在捕获阶段执行
以上是关于事件流 事件冒泡和事件捕获的主要内容,如果未能解决你的问题,请参考以下文章