第一章 js基础学习,事件流机制记录

59 阅读5分钟

事件流机制包括三个阶段

1.事件捕获

事件从外层节点一层一层往下走,直到捕获事件目标的位置。

当元素上绑定相同事件,触发之后就会像石头落水直到底部。

如图所示:

2022-07-04_164035.png

通过代码来实现下捕获的过程:

1.HTML代码块

	<div class="a">
	     <div class="b">
		<div class="c">目标元素</div>
	     </div>
	</div>

2.js代码块

(注:addEventListener是为元素绑定事件的方法,接收三个参数。第一个参数:绑定的事件名,第二个参数:执行的函数,第三个参数: false:默认,代表冒泡时绑定,true:代表捕获时绑定,需要改为true才能看见捕获效果。)

	let a=document.querySelector(".a");
	let b=document.querySelector(".b");
	let c=document.querySelector(".c");
		  
		  
	a.addEventListener('click',function(){
		alert("我是最外层:a")
	},true)
				  
	b.addEventListener('click',function(){
		alert("我是中间层:b")
	},true)
		
	c.addEventListener('click',function(){
		alert("我是最里层:c")
	},true)

通过点击不同目标元素查看效果

当点击最外层a时,只显示a。

如图所示:

image.png

当点击中间的b时,先显示a,再显示b

如图所示:

image.png

image.png

当点击最里面一层的c时,先显示a,再显示b,最后显示c

如图显示:

image.png

2.事件目标

真正触发事件的对象,既被点击的那个节点。

3.事件冒泡

事件从目标节点往上走,其祖先元素的相同事件也会被触发。在开发中大部分冒泡都是有用的,根据具体需求处理,如果不需要事件冒泡可以通过事件对象来取消冒泡。

如图所示:

2022-07-04_164035.png

通过代码来实现下冒泡的过程:

addEventListener元素绑定事件的方法,第三个参数: false:默认,代表冒泡时绑定。

	let a=document.querySelector(".a");
	let b=document.querySelector(".b");
	let c=document.querySelector(".c");
		  
		  
	a.addEventListener('click',function(){
		alert("我是最外层:a")
	})
				  
	b.addEventListener('click',function(){
		alert("我是中间层:b")
	})
		
	c.addEventListener('click',function(){
		alert("我是最里层:c")
	})

当点击a时,只显示a

如图显示:

image.png

当点击b时,先显示b,再显示a

如图所示:

image.png

image.png

当点击c时,先显示c,再显示b,最后显示a

如图所示:

image.png

image.png

image.png

整个流程就是当触发一个元素的事件时,该事件从该元素的祖先元素传递下去,此过程为捕获,而到达此元素之后,又会向其祖先元素传播上去,此过程为冒泡

取消事件冒泡

cancelBubble 设置为 true就是取消冒泡,点击最里面一层c,只触发c,不会继续往上冒泡。

	c.addEventListener('click',function(event){
		event=event || window.event
		alert("我是最里层:c")
		event.cancelBubble = true //取消冒泡
			 
	})
		  

事件委托

把事件委托到它的父层或者更外层元素上,也就是事件绑定到祖父层。这样可以大量节省内存占用,减少事件注册,比如在ul上绑定事件,使li的都能被响应到。

target和currentTarget区别

target:触发事件的某个具体对象,就是触发事件的元素。

currentTarget:触发的事件处理函数所绑定的元素,恒等于this(非ie的dom2级事件中,ie事件中this指向window)

当事件不支持冒泡的时候,两者指的是同一个元素。

当事件支持冒泡时:比如父元素和子元素都绑定click事件,当点击子元素时,父元素的事件也会触发,此时父元素事件的currentTarget指向父元素,target指向子元素。

从事件捕获的角度来看下效果。

HTML代码块:

        <div class="a">
		a
		<div class="b">
			b
			<div class="c">c</div>
		</div>
	</div>

js代码块:

		let a=document.querySelector(".a");
		let b=document.querySelector(".b");
		let c=document.querySelector(".c");
		
		a.addEventListener('click',function(event){
			console.log("a")
			console.log(event.target);
			console.log(event.currentTarget);
		},true)
				  
		b.addEventListener('click',function(event){
			console.log("b")
			console.log(event.target)
			console.log(event.currentTarget)
		},true)
		
		c.addEventListener('click',function(event){
			console.log("c")
			console.log(event.target)
			console.log(event.currentTarget)
		},true)

当点击c时,控制台显示的结果。在捕获阶段,点击最里层c时。会先触发a,再b,最后触发事件目标c。所以控制台会按照顺序显示a>b>c的输出。

event.target都是输出的<div class="c">c</div>

image.png

通过控制台可以明显的看出event.target输出的就是事件目标的节点内容。event.currentTarget是绑定事件的元素,包含里面的节点内容。

点击b看看控制台的输出结果

捕获阶段,先输出a的内容,再输出目标事件b的内容

event.target都是输出的<div class="b">b<div class="c">c</div></div>

image.png

对比下this,看下结果:

js代码块:

		let a=document.querySelector(".a");
		let b=document.querySelector(".b");
		let c=document.querySelector(".c");
		
		a.addEventListener('click',function(event){
			console.log("a")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		},true)
				  
		b.addEventListener('click',function(event){
			console.log("b")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		},true)
		
		c.addEventListener('click',function(event){
			console.log("c")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		},true)

看下控制台输出的结果:

当点击c时,事件目标c的event.currentTarget,event.target,this都为true

a和b的currentTarget与this为true,target与this为false

image.png

从事件冒泡的角度来看下效果。

js代码块:

		let a=document.querySelector(".a");
		let b=document.querySelector(".b");
		let c=document.querySelector(".c");
		
		a.addEventListener('click',function(event){
			console.log("a")
			console.log(event.target);
			console.log(event.currentTarget);
		})
				  
		b.addEventListener('click',function(event){
			console.log("b")
			console.log(event.target)
			console.log(event.currentTarget)
		})
		
		c.addEventListener('click',function(event){
			console.log("c")
			console.log(event.target)
			console.log(event.currentTarget)
		})

当点击c时,控制台显示的结果。在冒泡阶段,点击最里层c时。控制台会按照冒泡顺序显示c>b>a。

event.target也都是输出的<div class="c">c</div>,就只是输出顺序与捕获相反。

image.png

点击b时,控制台输出结果,顺序与捕获相反。

image.png

对比下this,看下结果:

js代码块:

		let a=document.querySelector(".a");
		let b=document.querySelector(".b");
		let c=document.querySelector(".c");
		
		a.addEventListener('click',function(event){
			console.log("a")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		})
				  
		b.addEventListener('click',function(event){
			console.log("b")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		})
		
		c.addEventListener('click',function(event){
			console.log("c")
			console.log("event.currentTarget==this:"+(event.currentTarget==this))
			console.log("event.target==this:"+(event.target==this))
			console.log("event.target==event.currentTarget:"+(event.target==event.currentTarget))
		})

看下控制台输出的结果:

当点击c时,事件目标c的event.currentTarget,event.target,this都为true

a和b的currentTarget与this为true,target与this为false

image.png

点击b看看输出

事件目标b的event.currentTarget,event.target,this都为true

a的currentTarget与this为true,target与this为false

image.png

通过捕获和冒泡的输出结果来看:currentTarget是等于this,绑定事件函数的元素。

取消事件冒泡的角度来看下效果。

js代码块:

		let a=document.querySelector(".a");
		let b=document.querySelector(".b");
		let c=document.querySelector(".c");
		
		a.addEventListener('click',function(event){
			event=event || window.event
			event.cancelBubble = true //取消冒泡
			console.log("a")
			console.log(event.target);
			console.log(event.currentTarget);
		})
				  
		b.addEventListener('click',function(event){
			event=event || window.event
			event.cancelBubble = true //取消冒泡
			console.log("b")
			console.log(event.target)
			console.log(event.currentTarget)
		})
		
		c.addEventListener('click',function(event){
			event=event || window.event
			event.cancelBubble = true //取消冒泡
			console.log("c")
			console.log(event.target)
			console.log(event.currentTarget)
		})

点击c时,控制台就输出c的内容,event.target和event.currentTarget输出内容是一样的。

image.png

点击b时,event.target和event.currentTarget输出内容是一样的。

image.png

对比一下this,返回结果都是true

c.addEventListener('click',function(event){
			event=event || window.event
			event.cancelBubble = true //取消冒泡
			console.log("c")
			console.log(event.currentTarget==this)
			console.log(event.target==this)
			console.log(event.target==event.currentTarget)
		})

image.png

结束语:如发现文章错误的地方,有劳诸位及时指正,不足的地方也请也多多补充,表示感谢。