事件流和事件委托
- 事件流
- 事件委托
一、事件流
1.1、说明
事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候, 并不是只有当前被点击的元素会触发事件 , 而是所有元素都会触发事件。而如果我们想要只触发其中一个事件时,此时就需要取消冒泡或捕获。浏览器默认都是冒泡类型
由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡
1.2、捕捉
当你鼠标点击或触发一个dom事件时,浏览器会从根节点(Node)开始由外到内依次捕获注册了该dom事件的元素,然后再通过冒泡原理由内向外依次执行事件触发函数。
<body>
<div onclick="second"><!--从外向里捕获-->
<div onclick="first">重合起来就对了</div><!--从里向外冒泡-->
</div>
<script>
function second(){
console.log("外面的盒子");
}
function first() {
console.log("里面的盒子");
}
</script>
</body>
<!--
------------Console-----------
里面的盒子
外面的盒子
-->
1.3、冒泡
当你点击一个子元素时,所有注册了“onclick”事件函数的父元素,都会从里向外逐个触发该事件。
<div id="div1" onclick="open1()">
<input type="button" value="确定" onclick="close1()">
</div>
<script>
function open1() {
alert("盒子被点击了");//后弹出
}
function close1() {
alert("按钮被点击了");//先弹出
}
</script>
二、事件委托
2.1、为什么要用事件委托?
从性能上:在JavaScript中,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间(性能)。——>减少与dom的交互操作。
从内存上:每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大。——>减少函数数量
2.2、委托的原理
事件委托是利用事件的冒泡原理来实现的。
2.3、委托的实现
- 不通过委托,如果我们要给
div
中的p
注册"onclick"事件怎么做?
<div id="div1">
<p>1111111</p>
<p>2222222</p>
<p>3333333</p>
</div>
<script>
let pList = document.getElementsByTagName("p");
for (let i=0;i<pList.length;i++){
pList[i].onclick=function () {
console.log(i);//onclick事件主体
}
}
</script>
10000个p定义10000个onclick?呵呵~
- 同样的需求,通过委托来实现
<div id="div1">
<p>1111111</p>
<p>2222222</p>
<p>3333333</p>
</div>
<script>
document.getElementById("div1").onclick=function (event) {
let target = event.target;//获取事件触发事件的节点对象
console.log();//onclick事件主体
};
</script>
内存和性能得到了很大的提升
- 如果每个子节点的触发事件都要实现不同的效果怎么办?
<div id="div1">
<p id="add">1111111</p>
<p id="remove">2222222</p>
<p id="write">3333333</p>
</div>
<script>
document.getElementById("div1").onclick=function (event) {
let target = event.target;//获取事件触发事件的节点对象
switch(target.id){
case "add":
console.log("add");
break;
case "remove":
console.log("remove");
break;
case "write":
console.log("write");
break;
}
};
</script>
其实是一样的,
- 那如果新增一个节点,新增的节点会有事件吗?
<div id="div1">
<p id="add">1111111</p>
<p id="remove">2222222</p>
<p id="write">3333333</p>
</div>
<input type="button" value="添加" id="input1">
<script>
document.getElementById("div1").onclick=function (event) {
let target = event.target;//获取事件触发事件的节点对象
switch(target.id){
case "add":
console.log("add");
break;
case "remove":
console.log("remove");
break;
case "write":
console.log("write");
break;
}
};
document.getElementId("input1").onclick=function () {
let newP = document.createElement("p");
newP.innerText = "新增";
$("div1").appendChild(newP);
};
</script>
还是一样的,新增节点也是有事件的,因为target是动态的?