说事件绑定得先说事件流
事件流 冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。【推荐】
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。
DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。
来个例子看一下吧!
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div id="myDiv">Click me!</div> </body> </html>当点击了div时事件流走向,
在冒泡型事件流中click事件传播顺序为:<div> =》<body> =》<html> =》document
在捕获型事件流中click事件传播顺序为:document =》<html> =》<body> =》<div>
这里之所以说冒泡,并不是视图上的冒泡,而是结构上的冒泡。这里要弄清楚了,就算在视图上div是独立的,但他的在html结构
结构上依旧是被body所包裹。而冒泡是由内而外向上冒泡。
懂了冒泡之后,捕获就好理解了,就是反向的事件流。由外而内。
事件处理 以上明白了事件流,现在说说怎样处理事件。
HTML事件处理:
直接在标签内绑定事件,例如:<button οnclick="something()"></button>
这里直接将js内something函数绑定到button上。
缺点:
1.一个方法需要多次引用,而且不符合 行为、结构、样式 相分离的原则。
2.当js的函数名更改,html标签内的方法也需要更改。
DOM 0级事件处理:
在<script>中获取dom元素绑定事件,例如:btn.onclick = function () {}
0级事件处理的较HTML事件处理的有点很明显,他完全写在<script>内,符合 行为、结构、样式 相分离的原则。还可以选出DOM元素集合通过for循环统一操作。
缺点:每个DOM元素只能绑定一个同类事件。例如绑定onclick,当你想在绑定onclick会发现他被覆盖了。
DOM 2级事件处理(事件监听)
addEventListener("事件名" , "事件处理函数" , "布尔值");
false 事件冒泡 true 事件捕获
优点相比前两个就多了。可以选择是事件流。可绑定多个同类事件。事件名可以组成字符串。
到今天的主题了~~
注意:removeEventListener() 不能移除匿名函数,像上面add()这种是可以的。removeEventListener需要知道你需要移出的是哪个事件处理函数。匿名函数丢弃了自身函数名,所以移出不了。
document.body.addEventListener('touchmove', function (event) { event.preventDefault(); },false);解释:只点击了button,但是包含button的div也执行了,这属于事件冒泡,事件逐级向上传递,传给了div,有时并不需要事件冒泡,可以通过stopPropagation()
<div id="div"> <button id="btn">按钮</button> </div> <script> document.getElementById("btn").addEventListener("click",showType); document.getElementById("div").addEventListener("click",showDiv); function showType(event){ alert(event.type); event.stopPropagation(); } function showDiv(){ alert("div"); } </script>这里归类可能没归好,也看看吧
传统的事件处理中,需要为每个元素添加事件处理器。js事件代理则是一种简单有效的技巧,通过它可以把事件处理器添加到一个父级元素上,从而避免把事件处理器添加到多个子级元素上。
事件代理的原理用到的就是事件冒泡和目标元素,把事件处理器添加到父元素,等待子元素事件冒泡,并且父元素能够通过target(IE为srcElement)判断是哪个子元素,从而做相应处理
传统事件处理,为每个元素添加事件处理器,代码如下:
<!DOCTYPE html> <html lang="zh"> <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> </head> <body> <ul id="color-list"> <li>red</li> <li>orange</li> <li>yellow</li> <li>green</li> <li>blue</li> <li>indigo</li> <li>purple</li> </ul> <script> (function(){ var colorList=document.getElementById("color-list"); var colors=colorList.getElementsByTagName("li"); for(var i=0;i<colors.length;i++) { colors[i].addEventListener('click',showColor,false); }; function showColor(e) { e=e||window.event; var targetElement=e.target||e.srcElement; alert(targetElement.innerHTML); } })(); </script> </body> </html>事件代理的处理方式,代码如下:
<!DOCTYPE html> <html lang="zh"> <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> </head> <body> <ul id="color-list"> <li>red</li> <li>orange</li> <li>yellow</li> <li>green</li> <li>blue</li> <li>indigo</li> <li>purple</li> </ul> <script> (function(){ var colorList=document.getElementById("color-list"); colorList.addEventListener('click',showColor,false); function showColor (e) { e=e||window.event; var targetElement=e.target||e.srcElement; if(targetElement.nodeName.toLowerCase()==="li"){ alert(targetElement.innerHTML); } } })(); </script> </body> </html>事件代理的好处
总结一下事件代理的好处:
将多个事件处理器减少到一个,因为事件处理器要驻留内存,这样就提高了性能。想象如果有一个100行的表格,对比传统的为每个单元格绑定事件处理器的方式和事件代理(即table上添加一个事件处理器),不难得出结论,事件代理确实避免了一些潜在的风险,提高了性能。 DOM更新无需重新绑定事件处理器,因为事件代理对不同子元素可采用不同处理方法。如果新增其他子元素(a,span,div等),直接修改事件代理的事件处理函数即可,不需要重新绑定处理器,不需要再次循环遍历。 而代理事件需要注意的是事件冒泡, 例如:Li里有span,这时我只想操作Li那我就要用到阻止冒泡了。
转载地址:https://blog.csdn.net/weixin_40122996/article/details/82533223