前端知识点---事件委托和机制-阻止冒泡机制-阻止默认行为机制(javascript)
文章目录
- 事件委托机制
- ✅ 事件委托的核心原理
- 🔎 为什么使用事件委托?
- 🧑💻 事件委托示例
- ⚡ 事件委托的注意事项
- 事件委托不适合的场景:
- 阻止冒泡机制
- ✅ 具体含义:
- 🧑💻 示例解析
- 🚦 注意事项
- 阻止默认行为机制
事件委托机制
事件委托(Event Delegation)
事件委托是一种将事件监听器绑定到父元素上,利用事件冒泡机制来处理子元素事件的技术。即使子元素是动态生成的,也可以通过事件委托轻松捕获并处理它们的事件。
✅ 事件委托的核心原理
事件冒泡:当一个元素上的事件被触发时,事件会从目标元素向上冒泡到其父元素,直至根元素(document)。
利用冒泡:通过给父元素绑定事件监听器,可以捕捉到所有子元素触发的事件。
减少事件绑定次数:即使有大量子元素,也只需绑定一次事件,提升性能。
🔎 为什么使用事件委托?
高效:避免为每个子元素单独绑定事件,减少内存占用。
适用动态内容:适合处理由 JavaScript 动态生成的元素。
代码简洁:简化代码结构,易于维护。
🧑💻 事件委托示例
假设你有一个待办事项列表,每个li是动态生成的,我们需要点击某个li时删除它。
❌ 不用事件委托(直接绑定事件)
// 每次添加 li 时都绑定一个事件
function addItem(text) {
const li = document.createElement('li');
li.textContent = text;
document.querySelector('ul').appendChild(li);
// 为每个 li 绑定事件
li.addEventListener('click', function () {
li.remove();
});
}
缺点:如果有成千上万个li,内存消耗会很大。
✅ 使用事件委托
// 父元素 ul 绑定事件
document.querySelector('ul').addEventListener('click', function (e) {
// 判断是否点击的是 li 元素
if (e.target.tagName === 'LI') {
e.target.remove(); // 删除被点击的 li
}
});
优点:
只需要一次事件绑定。
即使后续有更多li元素被添加,也会自动生效。
代码简洁高效。
⚡ 事件委托的注意事项
-
事件目标的判断:
使用 e.target 来获取实际触发事件的元素,并通过 tagName 或 classList 判断是否为需要的目标元素。 -
阻止冒泡或默认行为:
如果需要阻止事件进一步冒泡,可以使用 e.stopPropagation()。
事件委托不适合的场景:
-
如果子元素数量极少,直接绑定事件可能更加直观。
-
focus、blur 等不冒泡的事件无法使用事件委托。
阻止冒泡机制
e.stopPropagation()意思是在子元素冒泡到父元素的时候就已经被拦截
e.stopPropagation() 的作用是 阻止事件继续冒泡,让事件不会再传递到父元素。
✅ 具体含义:
e.stopPropagation():阻止事件从当前目标元素继续向上冒泡,不会触发父元素的事件监听器。
它只影响冒泡阶段,不影响捕获阶段。
🧑💻 示例解析
<div id="parent" style="width:300px;height:300px;background-color:lightblue;">
<button id="child" style="width:100px;height:100px;">点击我</button>
</div>
<script>
document.getElementById('parent').addEventListener('click', function() {
console.log('父元素被点击');
});
document.getElementById('child').addEventListener('click', function(e) {
console.log('子元素被点击');
e.stopPropagation(); // 阻止事件冒泡
});
</script>
执行效果:
点击按钮时:
子元素监听器执行 → console.log(‘子元素被点击’) 父元素不会被点击
由于 e.stopPropagation() 阻止了事件冒泡,父元素监听器不会执行。
点击父元素空白区域时:
只有父元素监听器执行 → console.log(‘父元素被点击’)
🚦 注意事项
不会影响同一元素上的其他事件:
e.stopPropagation() 只阻止事件冒泡,不会阻止同一元素上的其他事件执行。
不会阻止默认行为:
如果你想阻止默认行为(如表单提交、链接跳转),需要使用 e.preventDefault()。
不会影响事件捕获阶段:
在捕获阶段(从根元素向目标元素传递的过程)e.stopPropagation() 无效。
🚀 总结
使用场景:当你需要阻止事件冒泡,避免父元素的事件触发时。
常用于:模态框、下拉菜单、弹窗等场景,防止点击事件传递到背景元素导致意外关闭
阻止默认行为机制
e.preventDefault()
<form action="">
<input type="text" class="input">
<button class="button">提交</button>
</form>
document.getElementsByClassName('button')[0].addEventListener('click', function(e){
if(document.getElementsByClassName('input')[0].value.length<6){
alert("长度不够")
e.preventDefault()
}
})
document.getElementsByClassName(‘button’).addEventListener这样写是错误的
getElementsByClassName 没有直接的 addEventListener 方法
document.getElementsByClassName(‘button’) 返回的是一个 HTMLCollection(类似数组),即使只有一个元素,它也不是单一的元素对象。input也是一样
- document.getElementById():获取一个
- document.querySelector():获取一个
- 其他的都是获取的数组形式
document.getElementsByClassName('button')
console.log(document.getElementsByClassName('button'));
document.getElementsByClassName('input')
console.log(document.getElementsByClassName('input'));
第二:
按钮 如果不是在表单内,所以它没有默认的提交行为,e.preventDefault() 实际上不会有任何作用。
所以input跟button必须都要被form标签包裹着