一.什么是事件监听?
在javascript中,事件监听是一种允许你响应用户操作或其他浏览器事件(如点击、键盘输入、页面加载等)的机制
在JS中若要进行事件的监听,dom元素发生驱动行为也可以使用事件绑定的方法,这种方法直观,但通常不推荐用于大型或复杂的项目中,因为它会导致HTML和JavaScript代码的混合,不利于代码的维护和分离。
举个例子(下面代码采用了事件绑定的方式对box这个dom元素进行点击行为)
var box = document.querySelector(".box");
// 2事件绑定 只执行最后一次
box.onclick = function () {
console.log("111");
};
box.onclick = function () {
console.log("222");
};
box.onclick = function () {
console.log("333"); //333
};
在控制台点击了box这个dom元素,我们发现只打印输出了333这段代码。
为什么会出现这种情况呢?
在javaScript中给同个dom元素用事件绑定的方式对dom元素绑定多个行为,它会覆盖之前的驱动事件,只执行最后一次事件行为,这就是为什么只出现333,而不出现111,222的原因。
那么我们就可以使用(addEventListener)对事件进行监听,监听到的事件每一次都能执行。
box.addEventListener("click", function () {
console.log("111"); //111
});
box.addEventListener("click", function () {
console.log("222"); //222
});
box.addEventListener("click", function () {
console.log("333"); //333
});
在上面的代码中,在控制台的输出是111,222,333
二.理解嵌套关系的事件绑定和监听
//在html body内书写三个嵌套标签
<div class="one">
<div class="two">
<div class="three"></div>
</div>
</div>
<script>
//获取标签
var one=document.querySelector('.one')
var two=document.querySelector('.two')
var three=document.querySelector('.three')
// 2)事件绑定 (从里往外依次执行事件) three two one
one.onclick=function(){
console.log('one');
}
two.onclick=function(){
console.log('two');
}
three.onclick=function(){
console.log('three');
}
// 3)事件监听(第三个参数不填时默认是false,默认是事件冒泡) three two one
one.addEventListener('click',function(){
console.log('one');
},false)
two.addEventListener('click',function(){
console.log('two');
},false)
three.addEventListener('click',function(){
console.log('three');
},false)
// 输入的是true,则从外到内监听,属于捕获行为 one two three
one.addEventListener('click',function(){
console.log('one');
},true)
two.addEventListener('click',function(){
console.log('two');
},true)
three.addEventListener('click',function(){
console.log('three');
},true)
</script>
可以看到在标签中one包着two,two包着three;点击three盒子,在事件绑定中,从里到外执行事件,先执行three、two、one。在事件监听中,不填false,默认是冒泡行为。输入的是true,从外到内监听,属于捕获行为。在控制台上输出是one、two、three
三.如何阻止事件捕获和事件冒泡?
1.事件捕获
// 4)阻止事件捕获 function要添加参数 one two three
one.addEventListener('click',function(e){
// 阻止事件捕获(阻止监听同一事件的其他事件监听器被调用)
e.stopImmediatePropagation()
console.log('one');
},true)
two.addEventListener('click',function(){
console.log('two');
},true)
three.addEventListener('click',function(){
console.log('three');
},true)
2.事件冒泡
// 5)阻止事件冒泡 //three two one
one.addEventListener('click',function(){
console.log('one');
},false)
two.addEventListener('click',function(){
console.log('two');
},false)
three.addEventListener('click',function(e){
// 阻止其他事件监听器被调用
e.stopPropagation()
console.log('three');
},false)
四.什么是事件委托?
事件委托就是把原本要绑定在子元素上的事件绑定在父元素的身上,通过事件对象上的target属性去判断是哪一个子元素触发了事件,再进行相应的操作。使用事件委托可以减少dom操作,优化web性能,可以动态的对元素的添加和移除实现动态元素的绑定 。
当子元素上的事件被触发时,由于事件冒泡机制,这个事件会冒泡到父元素或祖先元素,从而触发在父元素或祖先元素上设置的事件监听函数。然后,通过判断事件发生的元素DOM类型,父元素或祖先元素可以做出不同的响应。
<ol>
<li class="active">导航1</li>
<li>导航2</li>
<li>导航3</li>
<li>导航4</li>
<li>导航5</li>
</ol>
<!-- 事件委托 本应该给li标签绑定事件的,结果给li标签的父元素或者祖先元素绑定事情 -->
<script>
// 获取ol标签
var ol = document.querySelector("ol");
// ol这个父元素绑定事件
ol.onclick = function (event) {
// 1.获取事件源
var el = event.target;
console.dir(el);
// 2. 判断点击的标签是否为li标签,为li标签设置高亮
if (el.tagName === "LI") {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
el.className = "active";
}
};
</script>
在上面代码中对ol绑定了事件监听,可以通过target去获取事件源,事件对象就是触发事件所产生的数据集合。
如此一个tab选项卡就完成了
事件委托可以动态添加(添加了元素可以同样动态绑定了事件)
例子:
// 事件委托可以动态添加
// 创建一个li标签
var li = document.createElement("li");
li.innerHTML = "导航6";
ol.appendChild(li);
如此,动态添加的导航6元素就可以使用ol所绑定的事件啦。
事件委托的好处 ?
1.提高性能:事件委托通过减少需要绑定的事件监听器的数量,来优化性能。只需在父级或祖先元素上添加一个事件处理程序,就可以管理其所有后代元素上的同一类型事件,这样就降低了内存占用。
2.动态监听:对于动态添加到页面中的元素,由于它们的事件监听器是绑定在父级或祖先元素上的,因此这些新元素也能自动获得事件监听功能,无需重新绑定事件。
3.避免内存泄漏:在低版本的IE浏览器中,如果删除元素而没有移除事件监听器,可能会导致内存泄漏。而使用事件委托,由于事件监听器是绑定在父级或祖先元素上的,即使子元素被删除,也不会影响事件监听器的存在,从而避免了内存泄漏的问题。
事件委托是一种强大且灵活的事件处理机制,特别适用于需要处理大量相似元素或动态添加元素的情况。