首先,大家需要了解 CSS 的两种事件模型:冒泡和捕获。冒泡模型是指事件先在嵌套层级较深的元素(子元素)触发,然后再逐层往上冒泡到外层的元素(父元素),而捕获则相反,事件会从外层开始逐层往下捕获到目标元素。在事件触发时,默认是先冒泡后捕获。
// 冒泡模型document.getElementById('child').addEventListener('click', function() { console.log('child clicked') }) document.getElementById('parent').addEventListener('click', function() { console.log('parent clicked') }) 点击 child 会输出: child clicked parent clicked // 捕获模型document.getElementById('child').addEventListener('click', function() { console.log('child clicked') }, true) // 捕获 document.getElementById('parent').addEventListener('click', function() { console.log('parent clicked') }, true) 点击 child 会输出: parent clicked child clicked
大家可以利用事件模型来防止事件穿透。比如,在需要防止事件穿透的元素上,设置 pointer-events 属性为 none,这样点击事件就会直接落在下方的元素上,而不会穿透到下下层的元素上。当然,这种方法只适用于支持 pointer-events 属性的浏览器。
// 防止事件穿透的元素// 下方的元素Click me!点击 grand-child 不会触发 child 的点击事件。
另外,大家也可以利用 event.stopPropagation() 来防止事件穿透。在子元素上捕获事件,并在事件处理函数中调用 event.stopPropagation() 即可防止事件冒泡至父元素。
document.getElementById('child').addEventListener('click', function(event) { console.log('child clicked') event.stopPropagation() }) document.getElementById('parent').addEventListener('click', function() { console.log('parent clicked') }) 点击 child 不会触发 parent 的点击事件。
总之,在开发过程中,大家需要根据具体情况,灵活运用事件模型和属性来防止事件穿透,从而提升用户体验。