DOM事件机制

197 阅读3分钟

事件

DOM事件机制,就是通过监听函数(listener)对事件做出反应。事件发生后,浏览器监听到了这个事件,就会执行对应的监听函数。

绑定事件

给元素添加事件称为绑定事件 绑定事件有2种方式:传统绑定 和 监听绑定

传统方式

利用on开头的事件 如onclick

div.onclick = function(event){ console.log('触发事件') };

特点:绑定事件的唯一性,同一个元素同一个事件只能设置一个处理函数,最后绑定的处理函数将会覆盖前面注册的处理函数

div.onclick = function(event){ console.log('hi') };

div.onclick = function(event){ console.log('hello') };最后只输出hello

监听绑定

W3C标准推荐的绑定方式,通过addEventListener()绑定

IE9之前的IE不支持此方法,可使用attachEvent()代替

element.addEventListener('click',fn,bool)

如果bool不传或值为falsy 就让监听处理函数fn走冒泡,即当浏览器在冒泡阶段发现element有fn监听函数,就会调用fn,并提供事件信息。

如果bool为ture 就让监听处理函数fn走捕获,即当浏览器在捕获阶段发现element有fn监听函数,就会调用fn,并提供事件信息。

特点:同一个元素同一个事件可以绑定多个监听

div.addEventListener('click',function()=>{
  alert('hi'); })
div.addEventListener('click',function()=>{
  alert('hello'); })
  //会先跳出hi接着跳出hello

事件的传播

事件(鼠标点击,鼠标经过等等事件)发生时会在元素节点之间按照特定的顺序传播 事件传播方式有分捕获和冒泡,根据事件在元素节点之间的传播顺序不同来区分 比如给一个div注册了点击事件:

image.png

捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素找监听函数的过程

冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点找监听函数的过程。

<div class='爷爷'>
 <div class='爸爸'>
   <div class='儿子'>
         文字
   </div>
 </div>
</div>

给三个div分别添加事件监听fnYe /fnBa /fnEr,点击文字,最先调用fnYe /fnBa /fnEr中的哪一个函数?

事件捕获:按爷爷=》爸爸=》儿子 的顺序看有没有函数监听

事件冒泡:按儿子=》爸爸=》爷爷 的顺序看有没有函数监听

术语

从外向内找监听函数,叫事件捕获

从内向外找监听函数,叫事件冒泡

事件委托

事件委托的原理:由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。

事件委托的具体操作:

场景一

要给100个按钮添加点击事件,咋办? 答:监听这100个按钮的祖先,等冒泡的时候判断target(e.target可返回触发事件的对象)是不是这100个按钮中的一个。

<div id=div1>
<span>span1</span>
<button>click 1</button>
<button>click 2</button>
          ...
<button>click 100</button>
</div>

<script>
div1.addEventListener('click',(e)=>{
const t = e.target
if(t.tagName.toLowerCase()==='button'){
console.log(button被点击了)
console.log('button内容是'+t.textContent)//可知道是第几个按钮被点击了
 }
})
</script>

场景二

要监听目前不存在的元素的点击事件,咋办? 答:监听祖先,等点击的时候看看是不是我想要监听的元素即可。

setTimeout(()=>{
 const button =document.createElement('button')
 button.textContent = 'click 1'
 div1.appendChild(button)
 },1000)
 
 div1.addEventListener('click',(e)=>{
  const t = e.target
 if(t.tagName.toLowerCase()==='button'){
console.log(button被点击了)
 }
})