面试题:什么是事件委托? 怎么阻止默认动作? 怎么阻止事件冒泡?

简介: 面试题:什么是事件委托? 怎么阻止默认动作? 怎么阻止事件冒泡?

面试题:什么是事件委托? 怎么阻止默认动作? 怎么阻止事件冒泡?


1.什么是事件委托?

事件委托也称之为事件代理(Event Delegation)。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。

举例:比如一个宿舍的同学同时快递到了,一种方法就是他们一个个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一

一分发给每个宿舍同学; 在这里,取快递就是一个事件,每个同学指的是需要响应事件的 DOM

元素,而出去统一领取快递的宿舍长就是代理的元素,所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个。

一个事件触发后,会在子元素和父元素之间传播(propagation),
这种传播分成三个阶段。

(1)捕获阶段:从window对象传导到目标节点(上层传到底层)称为“捕获阶段”(capture phase),捕获阶段不会响应任何事件;

(2)目标阶段:在目标节点上触发,称为“目标阶段”

(3)冒泡阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling

phase)。事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层

事件委托的优点:

【1】可以大量节省内存占用,减少事件注册。比如在ul上代理所有li的click事件就非常棒

<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
1234567

如上面代码所示,如果给每个li列表项都绑定一个函数,那对内存的消耗是非常大的,因此较好的解决办法就是将li元素的点击事件绑定到它的父元素ul身上,执行事件的时候再去匹配判断目标元素。

【2】可以实现当新增子对象时无需再次对其绑定(动态绑定事件)



假设上述的例子中列表项li就几个,我们给每个列表项都绑定了事件; 在很多时候,我们需要通过 AJAX

或者用户操作动态的增加或者删除列表项li元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;

如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的;所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。

使用事件委托注意事项:使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。

2.怎么阻止默认动作?

有一些html元素默认的行为,比如说a标签,点击后有跳转动作;form表单中的submit类型的input有一个默认提交跳转事件;reset类型的input有重置表单行为。

如果你想阻止这些浏览器默认行为,JavaScript为你提供了方法。

如下代码:

var $a = document.getElementsByTagName("a")[0];
$a.onclick = function(e){
alert("跳转动作被我阻止了")
e.preventDefault();
//return false;//也可以
}
默认事件没有了。
1234567

既然return false 和 e.preventDefault()都是一样的效果,那它们有区别吗?当然有。 仅仅是在HTML事件属性 和

DOM0级事件处理方法中,才能通过返回 return false 的形式组织事件宿主的默认行为。

w3c 的方法是 e.preventDefault(),IE 则是使用 e.returnValue = false;
在支持 addEventListener() 的浏览器中,也能通过调用时间对象的 preventDefault()
方法取消时间的默认操作。不过,在 IE9 之前的 IE 中,可以通过设置事件对象的 returnValue 属性为 false

来达到同样的效果。下面的代码假设一个事件处理程序,它使用全部的三种取消技术:

function cancelHandler(event){  
  var event = event || window.event;  //用于IE  
  if(event.preventDefault) event.preventDefault();  //标准技术  
  if(event.returnValue) event.returnValue = false;  //IE  
  return false;   //用于处理使用对象属性注册的处理程序  
}  
123456
复制代码

当前的 DOM 事件模型草案定义了 Event 对象属性 defaultPrevented。

return false

javascript 的 return false 只会阻止默认行为,用 jQuery 的话既可以阻止默认行为又可以防止对象冒泡。

下面这个使用原生 JS,只会阻止默认行为,不会停止冒泡:

<div id='div'  onclick='alert("div");'>  
  <ul  onclick='alert("ul");'>  
    <li id='ul-a' onclick='alert("li");'>
        <a href="http://caibaojian.com/" id="testB" >caibaojian.com</a>
    </li> 
    </ul>  
</div>  
//浏览器 
var a = document.getElementById("testB");  
  a.onclick = function(){  
  return false;  
}
1234567891011121314151617

3.怎么阻止冒泡事件

w3c 的方法是 e.stopPropagation(),IE 则是使用 e.cancelBubble = true

handlebars
function stopBubble(e){
if(e&&e.stopPropagation){//非IE
e.stopPropagation();
}
else{//IE
window.event.cancelBubble=true;
}
}
123456789

在支持 addEventListener() 的浏览器中,可以调用事件对象的一个 stopPropagation()

方法已阻止事件的继续传播。如果在同一对象上定义了其他处理程序,剩下的处理程序将依旧被调用,但调用 stopPropagation()

方法可以在事件传播期间的任何时间调用,它能工作在捕获阶段、事件目标本身中和冒泡阶段。



IE9 之前的IE不支持 stopPropagation() 方法。相反,IE事件对象有一个 cancleBubble 属性,设置这个属性为

true 能阻止事件进一步传播。( IE8 及之前版本不支持事件传播的捕获阶段,所以冒泡是唯一待取消的事件传播。)



当前的 DOM 事件规范草案在 Event 对象上定义了另一个方法,命名为stopImmediatePropagation()。类似

stopPropagation(),这个方法组织了任何其他对象的事件传播,但也阻止了在相同对象上注册的任何其他事件处理程序的调用。

<div id='div' onclick='alert("div");'>  
  <ul onclick='alert("ul");'>  
    <li onclick='alert("li");'>test</li>  
  </ul>  
</div>
123456789
function stopHandler(event)  
    window.event?window.event.cancelBubble=true:event.stopPropagation();  
}


相关文章
|
11月前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
228 1
|
JavaScript 前端开发
【面试题】对JS中的事件冒泡、事件捕获、事件委托的理解
【面试题】对JS中的事件冒泡、事件捕获、事件委托的理解
170 0
|
机器学习/深度学习 人工智能 算法
强化学习从基础到进阶-常见问题和面试必知必答5::梯度策略、添加基线(baseline)、优势函数、动作分配合适的分数(credit)
强化学习从基础到进阶-常见问题和面试必知必答5::梯度策略、添加基线(baseline)、优势函数、动作分配合适的分数(credit)
|
机器学习/深度学习 人工智能 算法
强化学习从基础到进阶-常见问题和面试必知必答[1]:强化学习概述、序列决策、动作空间定义、策略价值函数、探索与利用、Gym强化学习实验
强化学习从基础到进阶-常见问题和面试必知必答[1]:强化学习概述、序列决策、动作空间定义、策略价值函数、探索与利用、Gym强化学习实验
|
JavaScript 前端开发 索引
手撕前端面试题(Javascript~事件委托、数组去重、合法的URL、快速排序、js中哪些操作会造成内存泄漏......
手撕前端面试题(Javascript~事件委托、数组去重、合法的URL、快速排序、js中哪些操作会造成内存泄漏......
263 0
手撕前端面试题(Javascript~事件委托、数组去重、合法的URL、快速排序、js中哪些操作会造成内存泄漏......
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
11月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
11月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
11月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
283 4