JS事件详细解析

一、事件流

1. 什么是事件流

事件流描述了页面接收事件的顺序,分为两种事件流,一种是事件冒泡,一种是事件捕获。

事件三要素:事件目标,事件对象,事件处理程序

2. 事件冒泡

事件冒泡:事件从最具体元素(文档树中最深的节点)开始触发,然后向上传播至没那么具体的元素(文档)

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>冒泡与捕获</title>
</head>
<body>
	<div class="outer">
		<div class="center">
			<div class="inner">
				
			</div>
		</div>
	</div>
</body>
</html>

  在这样一个例子中,如果inner上设置了click事件,那么点击inner后,inner首先触发click事件,然后click事件沿DOM树一直向上,在经过的每一个节点上依次触发,直到document对象(现代浏览器会一直冒泡到window对象)。
  其顺序为:inner --> center --> outer --> body -->html -->document
  注:只有拥有与被触发的事件相同的事件类型的事件处理程序,才能在冒泡阶段被调用

2.事件捕获

事件捕获:事件捕获是最不具体的节点先接收到事件,然后沿DOM树向下传播,最具体的节点最后接收到事件

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>冒泡与捕获</title>
</head>
<body>
	<div class="outer">
		<div class="center">
			<div class="inner">
				
			</div>
		</div>
	</div>
</body>
</html>

  在事件捕获中,如果inner上设置了click事件,click事件首先会由document对象捕获,然后沿DOM树依次向下传播,直到最具体的目标元素inner。
  其顺序为:document --> html --> body --> outer --> center --> inner

3. DOM事件流

事件流的三个阶段事件捕获到达目标事件冒泡
解释:首先发生事件捕获,为提前拦截事件提供了可能;然后实际的目标元素接收到事件;最后一个阶段事件冒泡,最迟要在这个阶段响应事件。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>冒泡与捕获</title>
</head>
<body>
	<div class="outer">
		<div class="center">
			<div class="inner">
				
			</div>
		</div>
	</div>
</body>
</html>

  依旧以这个为例,点击inner,目标元素div不会在捕获阶段接收到事件。这是因为捕获阶段从document到再到就结束了。在"到达目标"阶段,才会触发目标元素上的事件。然后在冒泡阶段,事件反向传播到document。

二、事件处理程序

1. 什么是事件处理程序

为响应事件而调用的函数被称为事件处理程序。事件处理程序的名字以on开头,所以click事件的事件处理程序名叫做onclick,load事件的处理程序叫做onload。

2.HTML事件处理程序

方式一:

<div class="outer">
	<div class="center">
		<div class="inner" onclick="console.log('hello')">
			
		</div>
	</div>
</div>

在需要触发事件的元素中添加以事件处理程序名字为属性名的属性,其属性值为一段可执行的javascirpt代码

方式二:

<script>
	function show(){
		console.log("hello");
	}
</script>
<input type="button" value="点击" onlick="show()">

3. DOM0事件处理程序

设置方式:将一个函数赋值给一个事件处理程序属性

<script>
window.onload = function() {
	var btn = document.getElementById("btn");
	btn.onclick = function() {
		console.log("hello");
	}
}

</script>
<button id="btn">点击</button>

注:
(1) 使用DOM0为事件处理程序赋值时,所赋函数被视为元素的方法(元素是一个对象),所以,事件处理程序在元素的作用域中运行,即this等于元素。这样就可以通过this访问元素的任何属性和方法。
(2) 这种方式添加的事件处理程序在冒泡阶段调用事件处理程序


移除事件处理程序:将事件处理程序属性设置为null;(设置为其他数据类型也行,但是不建议)
  btn.onclick = null;

4.DOM2事件处理程序

  1. 以下两个方法所有的DOM节点都可以调用
    事件处理程序赋值:addEventListener(‘事件类型’,事件处理函数,布尔值)
    移除事件处理程序:removeEventListener(‘事件类型’,事件处理函数,布尔值)
    布尔值为true: 在捕获阶段调用事件处理程序
    布尔值为false: 在冒泡阶段调用事件处理程序(默认)

    例子:

    <script>
    	var btn = document.getElementById("btn");
    	btn.addEventListener('click',function(){console.log(this.id)},false);
    </script>
    
  2. 移除事件处理程序的时候,参数要完全一致

    <script>
    		window.onload = function(){
    			var btn = document.getElementById("btn");
    			btn.addEventListener('click',function(){console.log(this.id)},false);
    			btn.removeEventListener('click',function(){console.log(this.id),false});
    		}
    </script>
    <button id="btn">点击</button>
    

    此时是无法移除事件处理程序的 ,因为在addEventListener()中传入的函数与removeEventListener()中传入的函数,两个函数是不同的。我们可以做如下处理,使两者传入的函数相同。

    <script>
    		function func(){
    			console.log(this.id);
    		}
    		window.onload = function(){
    			var btn = document.getElementById("btn");
    			btn.addEventListener('click',func,false);
    			btn.removeEventListener('click',func,false);
    		}
    </script>
    
  3. 可以为同一个事件添加多个事件处理程序,多个事件处理程序按添加顺序来触发

    <script>
    		function func(){
    			console.log(this.id);
    		}
    		window.onload = function(){
    			var btn = document.getElementById("btn");
    			btn.addEventListener('click',func,false);
    			btn.addEventListener('click',function(){console.log("haha")},false);
    		}
    </script>
    <button id="btn">点击</button>
    

5. DOM0事件与DOM2事件区别

  1. DOM0事件不能为相同类型事件添加多个事件处理程序,DOM2事件可以为相同类型事件添加多个事件处理程序。
  2. DOM0事件只能在事件冒泡阶段调用事件处理程序,DOM2事件可以在冒泡阶段调用事件处理程序,也可以在捕获阶段调用事件处理程序。
  3. 添加和删除事件处理程序的方式不同。

三、事件对象

1. 什么是事件对象

在DOM中发生事件时,所有相关信息都会被收集存在在一个名为event的对象中。这个对象包含了一些基本信息,比如导致事件的元素,发生的事件类型,以及可能与特定事件相关的任何其他数据。所有浏览器都支持这个event对象,尽管支持的方式不同。

2. DOM事件对象

  1. event对象是传递给事件处理程序的唯一参数。不管以哪种方式指定事件处理程序(DOM0或DOM2),都会传入这个event对象。

    <script>
    	window.onload = function(){
    		var btn = document.getElementById("btn");
    		btn.onclick = function() {
    			console.log(event.type);
    		}
    	}
    </script>
    <button id="btn">点击</button>
    
  2. 在HTML中使用event对象

    <button id="btn" onclick="console.log(event.target)">点击</button>
    
  3. 事件对象中的属性和方法
    (1)event.bubbles : 表示事件是否冒泡
    (2)event.cancelable :表示是否可以取消事件的默认行为
    (3)event.currentTarget :当前事件处理程序所在元素
    (4)event.target :事件目标
    (5)event.type:被触发的事件类型
    (6)event.eventPhase:调用事件处理程序的阶段
    (7)event.stopPropagation():取消所有后续事件捕获或事件冒泡。只有bubles为true才能调用
    (8)event.preventDefault() :取消事件的默认行为。只有cancelable为true才能调用

  4. this,currentTarget,target的区别
    在事件处理程序内部,this对象始终等于currentTarget的值。currentTarget指的是当前事件处理程序所在的元素。target指的是事件实际目标。

    <script>
    	window.onload = function(){
    		document.body.onclick = function(event){
    			console.log(event.currentTarget === document.body);	//true
    			console.log(this === document.body);				//true
    			console.log(event.target === document.getElementsByTagName('button')[0]);	//true
    		}
    	}
    </script>
    <button>点击</button>
    

四、事件类型

  1. UI事件
    (1)load:在window上表示当页面加载完成后触发,在img元素上表示当图片加载完成后触发
    (2)unload:在window上表示当前页面完全卸载后触发
    (3)error:在windo上表示当js报错时触发
    (4)select:在文本框(input和textarea)上表示,当用户选择了一个或多个字符时触发
    (5)resize:在window上表示窗口被缩放时触发
    (6)scrool:当用户滚动包含滚动条的元素时在元素上触发

  2. 焦点事件
    (1)blur:当元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持
    (2)focus:当元素获得焦点时触发。这个事件不冒泡。

  3. 鼠标事件
    (1)click:鼠标点击或按键盘回车
    (2)dbclick:鼠标双击
    (3)mousedown:按下任意鼠标键
    (4)mouseup:释放鼠标按键
    (5)mouseenter:光标从元素外部移入元素内部
    (6)mouseleave:光标从元素内部移移到元素外部
    (7)mousemove:鼠标在元素上移动时反复触发
    (8)mouseout:光标从一个元素移动到另一个元素时触发
    (9)mouseover:光标从元素外部移到元素内部

  4. 键盘事件
    keydown:键盘按键按下
    keyup:键盘按键松开
    event中有一个keyCode属性,保存了按键的按键码。

五、事件代理

1. 为什么要用事件代理

(1)添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间


(2)每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率越大

2. 事件代理的原理

事件代理的原理就是事件冒泡。将子元素的事件处理程序绑定到父元素上,然后通过冒泡,使父元素来触发事件处理程序。这样的话,只通过一个事件处理程序,就可以管理某一类的事件。

3. 如何设置事件代理

<script>
	outer.onclick = function(event) {
		event.target.innerHTML = "我变了";
	}
</script>
<div class="outer">
	<div class="center">
		<div class="inner" >
			
		</div>
	</div>
</div>

点击inner后
在这里插入图片描述
点击center后
在这里插入图片描述
注:使用事件代理后,不仅现有的子元素可以触发事件,添加的子元素可以触发事件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值