JavaScript事件对象
解决一个单一问题往往需要多个知识点的辅助,产生这个问题的原因也是对多个知识点的理解不够透彻。
事件对象
当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进事件响应函数,该事件对象包含了该事件的一切信息。
再IE8及以下浏览器中,是将事件对象作为window属性保存的

解决事件对象兼容性问题
事件冒泡-事件捕获
事件冒泡-事件捕获分别由微软和网景公司提出,这两种概念都是为了解决页面中事件发生顺序(事件流)而提出的
事件冒泡(主流)
考虑以下代码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>事件冒泡</title> 6 </head> 7 <body> 8 <div id="one"> 9 <div id="two"> 10 <div id="three"> 11 <p></p> 12 </div> 13 </div> 14 </div> 15 </body> 16 </html>
当给id为one,two,three的div绑定单击事件时
点击p标签会依次触发three,two,one的单击事件
将这种现象形象的称之为事件冒泡,如同水里的泡泡一样从水下浮上去
事件捕获
与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
事件委派(事件冒泡的应用)
将事件统一绑定至祖先元素,利用冒泡,在点击子类元素时,冒泡至父类元素完成点击响应事件
优点是只需要绑定一次点击响应事件,即使后续添加的子类元素也无需重新绑定
未使用事件委派
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>事件冒泡</title> </head> <body> <button type="button" id="btn">添加超链接</button> <ul id="ul"> <li><a href="javascript:;">超链接1</a></li> <li><a href="javascript:;">超链接2</a></li> <li><a href="javascript:;">超链接3</a></li> </ul> </body> <script type="text/javascript"> //为每一个超链接绑定单击响应函数 var allA = document.getElementsByTagName("a"); for(var i=0;i<allA.length;i++){ allA[i].onclick = function(){ alert("a") } } //点击button按钮添加li标签 var btn = document.getElementById("btn"); btn.onclick = function(){ var li = document.createElement("li"); li.innerHTML = "<a href='javascript:;'>新建的li</a>"; var ul = document.getElementById("ul"); ul.appendChild(li); } </script> </html>
使用事件委派
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>事件冒泡</title> </head> <body> <button type="button" id="btn">添加超链接</button> <ul id="ul"> <li><a href="javascript:;">超链接1</a></li> <li><a href="javascript:;">超链接2</a></li> <li><a href="javascript:;">超链接3</a></li> </ul> </body> <script type="text/javascript"> //为ul绑定单击响应事件 var ul = document.getElementById("ul"); ul.onclick = function(){ alert("a"); } //点击button按钮添加li标签 var btn = document.getElementById("btn"); btn.onclick = function(){ var li = document.createElement("li"); li.innerHTML = "<a href='javascript:;'>新建的li</a>"; ul.appendChild(li); } </script> </html>
可以看到代码简洁了许多,但问题也随之而来
ul是块级元素,占满一行,给ul绑定的点击响应函数是只要点击ul就会响应,这与我们的目标 ‘单机a标签响应的目的相差甚远’
点击红色区域就会响应

那么,该如何解决
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>事件冒泡</title> </head> <body> <button type="button" id="btn">添加超链接</button> <ul id="ul"> <li><a href="javascript:;" class="index">超链接1</a></li> <li><a href="javascript:;" class="index">超链接2</a></li> <li><a href="javascript:;" class="index">超链接3</a></li> </ul> </body> <script type="text/javascript"> //为ul绑定单击响应事件 var ul = document.getElementById("ul"); ul.onclick = function(event){ if(event.target.className == "index"){ alert("1"); } } //点击button按钮添加li标签 var btn = document.getElementById("btn"); btn.onclick = function(){ var li = document.createElement("li"); li.innerHTML = "<a href='javascript:;' class='index'>新建的li</a>"; ul.appendChild(li); } </script> </html>
在执行响应函数时,添加一个判断(触发事件的元素某个属性值是否为预期的属性值),进行响应
需要注意的是,这样做有隐患,因为class通常可以写多个,如
class="index main"
这个问题可以用正则表达式来判断解决
事件绑定
使用 object.function 的形式绑定响应函数,只能绑定一个,绑定多个后面的会覆盖前面的
addEventListener
使用该函数可以为同一个对象,同一个事件绑定多个响应函数
以下内容摘自JS中事件冒泡与捕获 - SegmentFault 思否
网景 和 微软 曾经的战争还是比较火热的,当时, 网景主张捕获方式,微软主张冒泡方式。后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡。
由此可见鲁迅先生所说的中国人喜欢用折中的方式解决问题,也并非是中国人独有的特点
addEventListener的第三个参数就是为冒泡和捕获准备的.
addEventListener有三个参数:
element.addEventListener(event, function, useCapture)
第一个参数是需要绑定的事件,onclick写为click
第二个参数是触发事件后要执行的函数
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
IE8中使用attachEvent来达到相同目的
element.attachEvent(event, function)
第一个参数是需要绑定的事件,onclick写为onclick
第二个参数是触发事件后要执行的函数
后绑定先执行
bind函数
function bind(obj,evenStr,callback){ if(obj.addEventListener){ //大部分浏览器 obj.addEventListener(evenStr,callback,false); }else{ //IE8及以下 obj.attachEvent("on"+evenStr,function(){ //统一this指向问题 callback.call(obj); }); } }

浙公网安备 33010602011771号