事件处理机制系列1-捕获和冒泡

  html、css和js作为前端开发三件套,切合密不可分,而在js中,事件系统可以说是同html、css的结合点,用户可以通过鼠标、键盘、触摸屏等事件途径触发页面做出相应反应。
  如《javascript高级程序设计》一书所说,浏览器页面就好比一组同心圆,那么这个圆心不是一个圆的圆心,而是所有圆的圆心。页面上一个按钮,这个按钮必然处于一个父级容器内部,所以点击触发这个按钮可以理解成也点击了这个父级容器,根据网页的层层嵌套关系,这个按钮就有间接有多个父级容器。
  事件流是描述了从页面接受事件的顺序,早期微软和Netscape针对事件流有相反的看法,前者定义事件冒泡,接受事件的对象由目标对象向父级对象层层扩散,直到顶级文档document对象,后者则反之,定义这一过程叫事件捕获,事件由外及里直到目标对象,两者虽然异曲同工,但早期各浏览器对对事件的支持程度不一,直到后面才规范成为DOM2级事件处理,即事件处理包括三个阶段:事件捕获阶段 => 处于目标阶段 =》 事件冒泡阶段。
  先给出一个小示例,为列表中的每一项添加点击事件:

<DOCTYPE html>
<html>
<head>
</head>
<body>
<ul id="ul">
<li value="1">1</li>
<li value="2">2</li>
<li value="3">3</li>
<li value="4">4</li>
<li value="5">5</li>
</ul>
<script type="text/javascript">=
	let lis = document.getElementsByTagName('li');
	for (let i = 0; i < lis.length; i++) {
		lis[i].onclick = function() {
			console.log(lis[i].value);
		}
	}
</script>
</body>
</html>

  上例中,为每个li元素绑定了一个click事件监听器,不过,虽然说满足了基本要求,但是缺点还是有的:

1. 主要容易造成浏览器端性能压力,当li项数量较多时,需要注册的监听器就相应增多;

  采用事件冒泡机制,将点击li点击事件的监听任务交由父级容器处理,则上例的js部分可如下改造:

	let ul = document.getElementById('ul');
	ul.addEventListener('click', function(e) {
		if (e.target.tagName.toLowerCase() === 'li') {
		  console.log(e.target.value);
		}
	}, false);

  事件捕获在使用上同事件冒泡类似,只是通过设置addEventListener方法的第三个参数为true即可,相对来说,优先考虑使用事件冒泡方法处理,但有些事件自身是没有冒泡事件而又想做特殊处理的,那就可以使用事件捕获了,下面展示一些无冒泡的事件:

1. UI事件: load  unload  scroll resize
2. 焦点事件: blur  focus
3. 鼠标事件 mouseleave  mouseenter

总结

   项目优化从点滴做起,通过事件流的委托机制,能够将子项的处理任务按需交给父项处理,从而减少事件处理器的生成。接下来的博文希望能进一步学习事件相关知识点,对事件的监听机制、事件循环、事件队列作一些浅薄学习。

posted @ 2019-04-18 15:28  boykait  阅读(238)  评论(0编辑  收藏  举报