捕获、冒泡和事件委托

it2023-11-21  77

DOM事件流

基本概念

“DOM2级事件”规定的事件包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。

以下面html为例:

<!DOCTYPE html> <html> <head> <title>Event Bubbling Example</title> </head> <body> <div id="myDiv">Click Me</div> </body> </html>

单击<div>元素会按照下图触发事件:

在DOM事件流中,实际的目标(<div>元素)在捕获阶段不会接收到事件。这意味着在捕获阶段,事件从document到<html>再到<body>后就停止了。下一个阶段是“处于目标”阶段,于是事件在<div>上发生,并在事件处理中被看成冒泡阶段的一部分。然后,冒泡阶段发生,事件又传播回文档。

事件委托

基本概念

此处引自知乎用户桐城的《JavaScript事件委托详解》

事件委托,一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。

举个例子,比如一个宿舍的同学同时快递到了,一种方法就是他们都傻傻地一个一个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人去拿好所有快递,然后再根据收件人一一分发给每个宿舍同学。 在这里,取快递就是一个事件,每个同学指的是需要响应事件的DOM元素,而出去领取快递的宿舍长就是代理的元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个。

以上引自知乎用户桐城的《JavaScript事件委托详解》,再次感谢!

接下来举个例子:

<button class="btn">添加li标签</button> <ul> <li>li1</li> <li>li2</li> <li>li3</li> <li>li4</li> <li>li5</li> </ul>

我们的需求是:

点击任意一个li元素,都打印出“li被点击了”这句话(点击事件);点击一次按钮,便添加一个li ;点击新添加的li,也会打印出“li被点击了”这句话(点击事件);

我们可以先获取到所有li标签,遍历,注册点击事件;然后给按钮添加点击事件,添加新的li;但最后一条要求却不好实现。

但如果用事件委托,事情便变得很简单了:

//获取ul元素 var ul = document.querySelector('ul'); //获取按钮button元素 var btn = document.querySelector('.btn'); //给按钮注册点击事件 btn.onclick = function() { //点击按钮之后,在原来基础上再添加一个li标签 ul.innerHTML += '<li>新的li标签</li>'; //给ul(父元素)注册事件 ul.addEventListener('click', function(e) { //判断e.target(鼠标点击的节点)是否是li元素。nodeName里面要大写。 if (e.target.nodeName == 'LI') { //如果是,那么,代码将被执行 console.log('li被点击了'); } });

这样就不需要一次次判断了,直接用e.target.nodeName来判断。

作用

1、减少内存消耗

不需要给每个子元素都注册事件,减少了计算机的内存消耗。

2、可以动态注册事件

可以给动态创建的元素事件注册事件的效果。如本例中,不断添加的li标签。

最新回复(0)