概述
在javascript里,事件委托是很重要的一个东西,事件委托依靠的就是事件冒泡和捕获的机制,我先来解释一下事件冒泡和事件捕获:
1、事件冒泡和事件捕获
事件冒泡:从当前触发的事件目标
一级一级往上
传递,依次触发,直到document为止。
事件捕获:从document开始触发,一级一级往下
传递,依次触发,直到真正事件目标为止。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<style type="text/css">
#box1 { width: 300px; height: 300px; background: blueviolet; }
#box2 { width: 200px; height: 200px; background: aquamarine; }
#box3 { width: 100px; height: 100px; background: tomato; }
div { overflow: hidden; margin: 50px auto; }
</style>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
<script>
function sayBox3() {
console.log('你点了最里面的box');
}
function sayBox2() {
console.log('你点了最中间的box');
}
function sayBox1() {
console.log('你点了最外面的box');
}
// 事件监听,第三个参数是布尔值,默认false,false是事件冒泡,true是事件捕获
document.getElementById('box3').addEventListener('click', sayBox3, false);
document.getElementById('box2').addEventListener('click', sayBox2, false);
document.getElementById('box1').addEventListener('click', sayBox1, false);
</script>
</body>
</html>
三个box,结构是父子关系,分别绑定了打印事件,现在我们来点击最中间的红色box:
我们发现,我们仅仅是点击了红色的box,但是绿色和紫色的box也被触发了打印事件,触犯顺序是 红色>绿色>紫色,这种现象就是事件冒泡
了。
把上面代码里监听事件的第三个参数改为true,然后点击红色的box:
只点击最中间的红色box,和上一次一样,也是三个box都触发了事件,但是顺序反过来了,紫色>绿色>红色,这种现象称为事件捕获
。
2、事件委托
事件委托又称之为事件代理,我们通过一个通俗的例子来解释
有三个同事预计会在周一收到快递,为了签收快递,有两种办法:1.三个人在公司门口等快递;2.委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收(可以给暂时不存在的节点也绑定上事件)。
再举一个例子:
现在有一个ul,ul里又有100个li,我想给这100个li都绑定一个点击事件,我们一般可以通过for循环来绑定,但是要是有1000个li呢? 为了提高效率和速度,所以我们这时可以采用事件委托,只给ul绑定一个事件,根据事件冒泡的规则,只要你点了ul里的每一个li,都会触发ul的绑定事件,我们在ul绑定事件的函数里通过一些判断,就可以给这100li都触发点击事件了。
具体怎么实现,看代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul id="isUl">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
function clickLi() {
alert('你点击了li');
}
document.getElementById('isUl').addEventListener('click', function(event){
// 每一个函数内都有一个event事件对象,它有一个target属性,指向事件源
var src = event.target;
// 我们判断如果target事件源的节点名字是li,那就执行这个函数
// target里面的属性是非常多的,id名、class名、节点名等等都可以取到
if(src.nodeName.toLowerCase() == 'li') {
clickLi() ;
}
});
</script>
</body>
</html>
这样我们就通过给ul绑定一个点击事件,让所有的li都触发了函数。
那如果想给不同的li绑定不同的函数怎么办?
假设有3个li,我们先写3个不同的函数,再给3个li设置不同的id名,通过判断id名是不是就能给不同的li绑定不同的函数啦:
<body>
<ul id="isUl">
<li id="li01">1</li>
<li id="li02">2</li>
<li id="li03">3</li>
</ul>
<script>
function clickLi01() {
alert('你点击了第1个li');
}
function clickLi02() {
alert('你点击了第2个li');
}
function clickLi03() {
alert('你点击了第3个li');
}
document.getElementById('isUl').addEventListener('click', function(event) {
var srcID = event.target.id;
if(srcID == 'li01'){
clickLi01();
}else if(srcID == 'li02') {
clickLi02();
}else if(srcID == 'li03') {
clickLi03();
}
});
</script>
</body>
这就是所谓的事件委托,通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数,从而提升速度。
3、阻止事件冒泡
event.stopPropagation()
开篇的第一个例子,假如我们真的只想点击最里面的那个红色box,不想另外两个box的事件被触发,我们可以在给红色box绑定事件的函数里这么写:
function sayBox3(event) {
// 阻止冒泡
event.stopPropagation();
console.log('你点了最里面的box');
}
document.getElementById('box3').addEventListener('click', sayBox3, false);
这样我们再点击红色的box,那就只会触发它本身的事件啦。
最后说一点,如果元素被阻止冒泡了,千万别去用事件委托的方式监听事件,因为事件委托的原理是利用事件冒泡,当冒泡被阻止,就无法监听了。
最后
以上就是冷静汽车为你收集整理的js——事件委托、事件冒泡和事件捕获的全部内容,希望文章能够帮你解决js——事件委托、事件冒泡和事件捕获所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复