JavaScript 事件-事件流,事件冒泡,事件捕获,事件绑定与解绑,事件委托、阻止冒泡、阻止默认行为详细篇

一、事件流

事件流描述的是从页面中接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。

事件流包括两种模式:冒泡和捕获

当一个DOM事件被触发时,它不仅仅只是单纯地在本身对象上触发一次,而是会经历三个不同的阶段:

捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象;
目标阶段:到达目标事件位置(事发地),触发事件;
冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象。

事件冒泡:

子集元素先触发,父级元素后触;(由内到外)

子集元素和父元素具备同样的事件,当触发子元素时,也会触发父元素的事件。
在这里插入图片描述

事件捕获:

父级元素先触发,子集元素后触发;(由外到内)

在这里插入图片描述

二、事件绑定与解绑

(1)element.addEventListener(event, function, useCapture);
element.removeEventListener(event, function, useCapture);IE8及以下不支持

IE不支持addEventListener和removeEventListener方法

第一个参数:必须。字符串,指定事件名。不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。

第二个参数:必须。指定要事件触发时执行的函数。

第三个参数:可选。布尔值,指定事件是否在捕获或冒泡阶段执行。
                      true - 事件句柄在捕获阶段执行
                      false- false- 默认。事件句柄在冒泡阶段执行

	var element=document.getElementById("box");
	var handler=function(){
	     event.preventDefault( );      //阻止默认事件
	}
	//绑定事件
	element.addEventListener('click', handler, false);  
	//解绑事件
	element.removeEventListener('click', handle, false);
(2)attachEvent(event.type, handle );
detachEvent("onclick", handler); IE特有,兼容IE8及以下,可添加多个事件处理程序,只支持冒泡阶段,并不属于DOM2

有类似于addEventListener的方法:attachEvent();detachEvent(); 区别就是attachEvent()的参数只有两个且和addEventListener()前两个参数一致,只支持冒泡

	var element=document.getElementById("box");
	var handler=function(){
	    event.returnValue = false;       //阻止默认事件
	}
	//绑定事件
	element.attachEvent('onclick', handler); 
	//解绑事件,参数和绑定一样
	element.detachEvent("onclick", handler);
(3)封装事件绑定与解绑函数,兼容浏览器
	//用事件冒泡方式,如果想兼容事件捕获只需要添加个bool参数
	var EventUtil = {
	    addEvent: function(element,type,handler) {
	        if (element.addEventListener) {
	            element.addEventListener(type,handler,false);
	        }
	        else if (element.attachEvent) {
	            element.attachEvent('on'+type,handler);
	        }
	        else {
	            element['on'+type] = handler;
	        }
	    },
	
	    removeEvent: function(element,type,handler) {
	        if (element.removeEventListener)
	        {
	            element.removeEventListener(type,handler,false);
	        }
	        else if(element.detachEvent) {
	            element.detachEvent('on' +type,handler);
	        }
	        else {
	            element['on'+type] = null;
	        }
	    }
	}

//如何调用

	var box= document.getElementById("box");
	var handler = function(){
	    console.log(111);
	};
	EventUtil.addEvent(box, "click", handler);
	EventUtil.removeEvent(box, "click", handler);

三、阻止冒泡

event.stopPropagation() 阻止事件冒泡的产生
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title></title>
		<style>
			#demo1 {
				width: 300px;
				height: 300px;
				background: red;
			}

			#demo2 {
				width: 200px;
				height: 200px;
				background: blue;
			}

			#demo3 {
				width: 100px;
				height: 100px;
				background: yellow;
			}
		</style>
		<script type="text/javascript">
			window.onload = function() {
				var demo1 = document.getElementById("demo1");
				var demo2 = document.getElementById("demo2");
				var demo3 = document.getElementById("demo3");
				var fnDome = function() {
					alert(this.id)
				}

				function fnStop() {
					alert(this.id);
					event.stopPropagation();
					//event.stopPropagation()	阻止事件冒泡的产生
					//Propagation(繁殖、传播 )
				}

				//单独一项一项测试时
				//demo1.addEventListener("click", fnDome, false);		//demo1,点击三个div都会弹出
				//demo2.addEventListener("click", fnDome, false);		//demo2,点击demo2,demo3两个div都会弹出
				//demo3.addEventListener("click", fnDome, false);		//demo3,点击demo3这个div
				//demo1.addEventListener("click", fnDome, true);		//demo1点击三个div都会弹出
				//demo2.addEventListener("click", fnDome, true);		//demo1,点击demo2,demo3两个div都会弹出
				// demo3.addEventListener("click", fnDome, true);		//demo1,点击demo3这个div

				//demo1.addEventListener("click", fnStop, false);		//demo1,点击三个div都会弹出
				//demo2.addEventListener("click", fnStop, false);		//demo2,点击demo2,demo3两个div都会弹出
				//demo3.addEventListener("click", fnStop, false);		//demo3,点击demo3这个div
				//demo1.addEventListener("click", fnStop, true);		//demo1,点击三个div都会弹出
				//demo2.addEventListener("click", fnStop, true);		//demo2,点击demo2,demo3两个div都会弹出
				//demo3.addEventListener("click", fnStop, true);		//demo3,点击demo3这个div
				//事件处理函数不能加括号,否则会直接执行
				//总结:当选中一个节点时,无论是冒泡还是捕获,里面的节点有同样的事件

				//第二次测试,合并测试,当一个事假有多个节点时
				// demo1.addEventListener("click", fnDome, false);		//一次,demo1
				// demo2.addEventListener("click", fnDome, false);		//二次,demo2,demo1
				// demo3.addEventListener("click", fnDome, false);		//三次,demo3,demo2,demo1
				//总结:冒泡事件按从内到外依次执行

				//第三次测试,合并测试,当一个事假有多个节点时
				// demo1.addEventListener("click", fnDome, true); 		 //demo1
				// demo2.addEventListener("click", fnDome, true);		 //demo1,demo2
				// demo3.addEventListener("click", fnDome, true);		 //demo1,demo2,demo3
				//总结:鋪貨事件按从外到内依次执行

				//第四次测试,合并测试,当一个事假有多个节点时 
				// demo1.addEventListener("click", fnStop, false);		 //demo1
				// demo2.addEventListener("click", fnStop, false); 		//demo2
				// demo3.addEventListener("click", fnStop, false);		 //demo3


				//第五次测试,合并测试,当一个事假有多个节点时 
				//demo1.addEventListener("click", fnStop, true);			//demo1
				demo2.addEventListener("click", fnStop, true);			//demo1
				demo3.addEventListener("click", fnStop, true);			//demo1

			}
		</script>
	</head>
	<body>
		<div id="demo1">1
			<div id="demo2">2
				<div id="demo3">3
				</div>
			</div>

		</div>
	</body>
</html>


总结:
(1)当选中一个节点时,无论是冒泡还是捕获,节点里面的节点有同样的事件

(2)当一个事件有多个节点时,冒泡事件按从内到外依次执行

(3)当一个事件有多个节点时,捕获事件按从外到内依次执行

(4)当一个事件有多个节点时,阻止事件冒泡的产生,冒泡事件,只会执行当前或包含的节点事件,不会冒泡,执行完里面节点的事件不会接着执行包含节点的节点事件,也就是说只会执行一次,如果不阻止事件冒泡的产生,则会将事件一个个执行完

(5)当一个事件有多个节点时,阻止事件冒泡的产生,捕获事件,只会执行第一个捕获到的事件

四、阻止默认

w3c 的方法是 e.preventDefault(),
IE 则是使用 e.returnValue =false;

preventDefault 它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。比如超链接a

	<body>
		<a href="事件冒泡.html" target="_blank">啦啦啦啦啦</a>
		<script type="text/javascript">
			var a1=document.getElementsByTagName('a')[0];
		//传统用法阻止事件的默认发生
//			a1.οnclick=function(e){
//				e.preventDefault();
//			}
		//使用DOM方法来阻止默认发生
			a1.addEventListener('click',show);
		//兼容
			function show(e){
				if (e.preventDefault) {
					e.preventDefault();
				} else{
					window.event.returnValue=false;
				}
			}
		</script>
	</body>

posted @ 2022-04-02 09:48  coderwcb  阅读(84)  评论(0编辑  收藏  举报