【DOM事件】DOM事件及事件委托

26 篇文章 0 订阅
10 篇文章 0 订阅

目录

  • 点击事件?
  • 事件的捕获和冒泡
  • addEventListener
  • 代码图解
  • target VS currentTarget
  • 事件委托
  • 自定义事件

三、点击事件

以下引出一个讨论的问题

<div class='爷爷'>
	<div class='爸爸'>
		<div class='儿子'>
		文字
		</div>
	</div>
</div>
<script>
	/* 均添加点击事件 */
	爷爷.addEventListener('click',fn);
	爸爸.addEventListener('click',fn);
	儿子.addEventListener('click',fn);
	</script>
  • 提问1:点击了谁,又算谁?点击了文字,算不算点击了儿子、算不算点击了爸爸、算不算点击了爷爷?
    • 答:都算!

  • 提问2:调用顺序? 最先调用fn爷、fn爸、fn儿中的那一个函数?
    • 答:都行!

四、事件的捕获与冒泡

  • 2002年,W3C发布标准

    文档名为:DOM Level 2 Events Specification

    规定浏览器应该同时支持两种调用顺序

    首先 按 “爷爷 -> 爸爸 -> 儿子” 的顺序看看有没有函数监听。

    然后 按 “儿子 -> 爸爸 -> 爷爷” 的顺序看看有没有函数监听。

    有函数监听就调用,并提供事件信息。没有就跳过。

  • 事件捕获:从外向内找监听函数 -- 捕获不可以取消

  • 事件冒泡:从内向外找监听函数 -- 冒泡可以取消

  • 问题来了:那岂不是fn爷fn爸fn儿都要调用两次?非也!开发者自己选择把函数监听调用放在捕获阶段还是冒泡阶段


五、addEventlistener

  • 事件绑定API

      绑定事件对象.addEventListener(事件类型,回调函数,布尔值) 
    
    1. 如果不传布尔值或为falsy值 – fn就会走冒泡阶段,
    2. 如果布尔值为true – fn 就会走捕获阶段
    1. 你可以选择将fn放在那一边。

  • 代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>冒泡demo</title>
</head>
<body>
<div class="level1 x">
  <div class="level2 x">
    <div class="level3 x">
      <div class="level4 x">
   	 <div class="level5 x">
   	   <div class="level6 x">
   		 <div class="level7 x">
   		 </div>
   	   </div>
   	 </div>
      </div>
     </div>
   </div>
</div>
<script>
   /* 要演示捕获阶段,将addEcentListener添加上第三个参数true即可 */

   const level1 = document.querySelector('.level1')
   const level2 = document.querySelector('.level2')
   const level3 = document.querySelector('.level3')
   const level4 = document.querySelector('.level4')
   const level5 = document.querySelector('.level5')
   const level6 = document.querySelector('.level6')
   const level7 = document.querySelector('.level7')

   let n = 1

   level1.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level2.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level3.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level4.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level5.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level6.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })

   level7.addEventListener('click', (e)=>{
   const t = e.currentTarget
   setTimeout(()=>{  
   	t.classList.remove('x')
   },n*1000)
   n+=1
   })
</script>
</body>
</html>


  • W3C事件模型

    1、先捕获,在冒泡

    2、注意 e对象被传给所有的监听函数

    3、事件结束后,e 对象也就不存在了。

    4、事件列表


六、target VS currentTarger

  • 区别
    1. e.target – 用户操作的元素
    2. e.currentTarget – 程序员监听的元素
    3. this就是e.currentTarget
  • 举例
      <div>
      	<span>文字</span>
      </div>
    
      | 当用户点击文字后,
      | e.target就是span
      | e.currengtTarget就是div
    
  • 一个特例

    只有一个元素被监听(不考虑父子同时被监听),fn 分别在捕获和冒泡阶段监听click事件,用户点击的元素就是开发者监听的

      <div>这是被监听的div</div>
      
      <script>
      let div=document.querySelector('div');
      div.addEventListener('click',()=>{
      	console.log(1);
      })	//冒泡阶段
      
      div.addEventListener('click',()=>{
      	console.log(2);
      },true)	//捕获阶段
      </script>
    
    请问:输出 1 2 ,还是输出 2 1?
    正确答案:谁先监听谁先执行。

七、事件委托

  • 情景一

    你要给100个按钮做监听事件,咋办?

  • 情景二

    你要监听目前不存在的元素的事件,咋办?

  • 正确方案:监听这些元素的祖先,等冒泡或事件触发时判断是不是我想要监听的元素即可。
  • 代码示例
      <!DOCTYPE>
      <html>
      <head>
      	<meta charset='UTF-8'>
      	<title>事件委托</title>
      <head>
      <body>
      	<div class='max'>
      		<button class='btn-1'>btn1</button>
      		<button class='btn-2'>btn2</button>
      		<button class='btn-3'>btn3</button>
      					.
      					. (省略96个button)
      					.
      		<button class='btn-100'>btn100</button>
      	</div>
      	<script>
      		 /* 监听祖先元素 */
      		 let btn_max=document.querySelector('.max');
      		 btn_max.addEventListener('click',()=>{
      			 const t = e.target;	//为了保存e.target对象,因为它是一个异步的结果,点击后e.target对象就会消失。
      			 if(e.tagName.toLowerCase()==='button'){
      				 console.log('button被点击了');
      				 console.log('被点击的button是'+ t.className);	//这样就能知道点击了哪一个button
      			 }
      		 })
      	</script>
      </body>
      <html>
    

八、自定义事件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
	<div id=div1>
		<button id=button1>点击触发 frank 事件     
		</button>
	</div>
	<script>
		button1.addEventListener('click', ()=>{
			const event = new CustomEvent("frank", {"detail":{name:'frank', age: 18}})
			button1.dispatchEvent(event)
		})

		button1.addEventListener('frank', (e)=>{
			console.log('frank')
			console.log(e)
		})
	</script>
</body>
</html>

以上代码就创建了一个自定义事件,详情更多内容

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值