接着上篇的节奏走,上篇文章我们介绍了事件冒泡的过程及解决方法。
这期带来事件代理~~
事件代理这个名词其实经常出现,在面试的时候,有一个高频问题,假如现在有需求,需要操作10000个DOM节点,你会怎么做?
就比如我们上篇用的案例,一个ul
,内部有n个li
。我现在要求你操作DOM
,生成10000个li
,并且分别给他们的点击事件绑定处理函数,输出自己的内容。
这种问题,显然不能用常规的办法,常规的办法,早就累死了。
其实面试官想考察的就是关于事件代理的相关内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father {
width: 200px;
height: 200px;
border: 1px solid #000;
}
.child {
width: 100px;
height: 100px;
}
.child.child-1 {
background-color: red;
}
.child.child-2 {
background-color: orange ;
}
</style>
</head>
<body>
<div class="father">
<div class="child child-1"></div>
<div class="child child-2"></div>
</div>
<script>
var oFather = document.getElementsByClassName('father')[0],
oChild1 = document.getElementsByClassName('child-1')[0],
oChild2 = document.getElementsByClassName('child-2')[0];
oFather.onclick = function(e) {
var e = e || window.event;
console.log(e);
}
</script>
</body>
</html>
还是上期的代码,我们把child-1
和child-2
的点击事件取消,只保留它们的父类father
的点击事件处理函数。并且在点击事件内容输出e
。
我们看下结果:
在输出结果中,往下找,有一个target
属性,可以看到,被点击的元素其实被保存到了这个target
属性里,那么我们分别输出一下它的className
和tagName
看看能否打印出来。
可以看到是可以的,即使我们不给子元素绑定任何的事件,也是可以通过父元素拿到它的className
和tagName
的,这和直接操作它的DOM
节点效果其实是差不多的。
这样,一个很棒的想法就冒了出来,既然我从父元素的点击事件中也可以拿到子元素的节点信息,那么我是不是就可以通过这个来区分子元素,并且绑定它对应的点击事件处理函数。
对的,这其实就是事件代理的思路,通过父元素来触发其子元素的某些事件,达到一个代理效果。
下面我贴一下完全代码。、
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father {
width: 200px;
height: 200px;
border: 1px solid #000;
}
.child {
width: 100px;
height: 100px;
}
.child.child-1 {
background-color: red;
}
.child.child-2 {
background-color: orange ;
}
</style>
</head>
<body>
<div class="father">
<div class="child child-1"></div>
<div class="child child-2"></div>
</div>
<script>
var oFather = document.getElementsByClassName('father')[0],
oChild1 = document.getElementsByClassName('child-1')[0],
oChild2 = document.getElementsByClassName('child-2')[0];
oFather.onclick = function(e) {
var e = e || window.event,
tar = e.target || e.srcElement, //兼容IE
tagName = tar.tagName.toLowerCase();
className = tar.className;
switch(className) {
case 'child child-1':
console.log('child-1');
break;
case 'child child-2':
console.log('child-2');
break;
case 'father':
console.log('father');
break;
default:
break;
}
}
</script>
</body>
</html>
这里面其实还有几个问题。
什么时候用tagName,什么时候用className呢?
当然要看实际的情况,如果子标签都是相同的,全是div
,那么肯定不能通过tagName
来,因为它们的tagName
都是DIV
。还有就是如果使用tagName
,记得转成小写,因为tagName
默认都是大写的。
如何兼容IE?
作为一个有素养的程序员,一定要考虑兼容问题,其实代码里我已经写出来了,如果要兼容IE浏览器,就把e.target
换成e.srcElement
,它们是一样的。
通过三次点击,可以看到,它正确的输出了各自应该输出的内容,这就很棒了~~
ok,关于事件冒泡和事件代理的相关内容就介绍到这里,有任何问题欢迎讨论交流。还有就是,我最近在找实习,有渠道的也可也i联系我哈~~
联系方式
QQ:505417246
微信:18331092918
微信公众号:Code程序人生