js之DOM事件机制(事件流、事件委托)


一、事件流

1)DOM事件流

DOM2 Events 规范规定事件流分为 3 个阶段事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。

1.捕获阶段
- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
2.目标阶段
- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3.冒泡阶段
- 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
- 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
在这里插入图片描述

2) 事件冒泡(Bubble)

  • 所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
  • 在冒泡中,最内侧元素的事件会首先被处理,然后是更外侧的:首先处理 <p> 元素的点击事件,然后是 <div>元素的点击事件。
  • 在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			#box1{
				width: 200px;
				height: 200px;
				background-color: yellowgreen;
			}
			
			#s1{
				background-color: yellow;
			}	
		</style>
		
	</head>
	<body>
		
		<div id="box1">
			我是box1
			<span id="s1">我是span</span>
		</div>
		
		<script type="text/javascript">
				//为s1绑定一个单击响应函数
				var s1 = document.getElementById("s1");
				s1.onclick = function(event){
					event = event || window.event;
					alert("我是span的单击响应函数");
					
					//取消冒泡
					//可以将事件对象的cancelBubble设置为true,即可取消冒泡,或者设置event.stopPropagation()
					//event.cancelBubble = true;
					//event.stopPropagation()
				};
				
				//为box1绑定一个单击响应函数
				var box1 = document.getElementById("box1");
				box1.onclick = function(event){
					event = event || window.event;
					alert("我是div的单击响应函数");
					
					//event.cancelBubble = true;
				};
				
				//为body绑定一个单击响应函数
				document.body.onclick = function(){
					alert("我是body的单击响应函数");
				};
			
		</script>
	</body>
</html>

运行结果:
点击span前:
在这里插入图片描述
点击span后:(引发各个祖先事件响应)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3) 事件捕获

  • 在捕获中,最外侧元素的事件会首先被处理,然后是更内侧的:首先处理外部元素的点击事件,然后是内部元素的点击事件。
    在这里插入图片描述

二、事件委托(事件代理)

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。将本应该绑定给子元素的事件代理给父元素
目的: 减少dom操作浏览器的重排和重绘,并且新添加的元素也是有事件的。

案例:

<script>
        window.onload = function() {
            // 要求给所有的li标签绑定事件 点击每一个li标签背景色变成红色
            var ul = document.getElementsByTagName('ul')[0];
            // var lis=document.getElementsByTagName('li');
            // for(let i=0;i<lis.length;i++){
            // 	lis[i].οnclick=function(){
            // 		this.style.backgroundColor='red'
            // 	}
            // }
            // 利用事件委托 利用事件冒泡(方法一)
            //ul.onclick = function(e) {
            //    e.target.style.backgroundColor = 'red';
            //}
            //var newLi = document.createElement('li');
            //newLi.innerHTML = '我是一个新的li';
            //ul.appendChild(newLi);
            
            // 事件委托 (方法二)
            ul.addEventListener('click', function(e) {
                if (e.target.localName === "li") {
                    e.target.style.backgroundColor = 'red';
                }
            })
        }
    </script>
</head>

<body>
    <ul>
        <li>1个li标签</li>
        <li>2个li标签</li>
        <li>3个li标签</li>
        <li>4个li标签</li>
        <li>5个li标签</li>
        <li>6个li标签</li>
        <li>7个li标签</li>
        <li>8个li标签</li>
        <li>9个li标签</li>
        <li>10个li标签</li>
    </ul>
</body>

运行结果:
在这里插入图片描述
事件委托的优点:

  • document 对象随时可用,任何时候都可以给它添加事件处理程序(不用等待 DOMContentLoaded或 load 事件)。这意味着只要页面渲染出可点击的元素,就可以无延迟地起作用。

  • 节省花在设置页面事件处理程序上的时间。只指定一个事件处理程序既可以节省 DOM 引用,也可以节省时间。

  • 减少整个页面所需的内存,提升整体性能

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值