DOM 事件模型

1,155 阅读3分钟

一、点击事件

示例代码:

<div class = 爷爷>
  <div class = 爸爸>
    <div class = 儿子>
      文字
      </div>
    </div>
  </div>
  
即.爷爷>.爸爸>.儿子
给三个div分别添加事件监听fnYe/fnBa/fnEr

提问一:点击了谁?

  • 点击文字,算不算点击儿子?
  • 点击文字,算不算点击爸爸?
  • 点击文字,算不算点击爷爷?
  • 答案:都算

提问二:调用顺序

  • 点击文字,最先调用fnYe/fnBa/fnEr中的哪一个函数?
  • 答案:都行

IE5认为先调fnEr,网景认为先调fnYe

  • 最后:W3C发布标准 文档名为DOM Level 2 Events Specification 规定浏览器应该同时支持两种调用顺序 首先按 爷爷=〉爸爸=> 儿子顺序看有没有函数监听 有监听函数就调用,并提供事件信息,没有就跳过

  • 冒泡是ie发明的

1、事件捕获:外向内找监听函数

2、事件冒泡:内向外找监听函数

事件冒泡:JS中当出发某些具有冒泡性质的事件是,首先在触发元素寻找是否有相应的注册事件,如果没有再继续向上级父元素寻找是否有相应的注册事件作出相应,这就是事件冒泡。

二、addEventListener

1、事件绑定API

IE5*:baba.attachEvent('onclick',fn) //冒泡

网景:baba.addEventListener('click',fn) //捕获

W3C:baba.addEventListener('click',fn,bool)

2、如果bool不传或为falsy

就让fn走冒泡,即当浏览器在冒泡阶段发现baba有fn监听函数,就会调用fn,并提供事件信息

3、如果bool为true

就让fn走捕获,即当浏览器在捕获阶段发现baba有fn监听函数,就会调用fn,并提供事件信息

小结

1、两个疑问

儿子被点击了,算不算点击老子?

那么先调用老子的函数还是先调用儿子的函数?

2、捕获与冒泡

捕获说先调用爸爸的监听函数

冒泡说先调用儿子的监听函数

3、W3C事件模型

先捕获(先爸爸=>儿子)再冒泡(再儿子=>爸爸)

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

事件结束后,e对象就不存在了

三、target vs currentTarget

区别

e.target-用户操作的元素

e.currentTarget-程序员监听的元素

this是e.currentTarget,老师不推荐使用

举例

div>span{文字},用户点击文字

e.target就是span

e.currentTarget就是div

一个特例

背景

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

请问,f1先执行还是f2先执行?
如果把两行调换位置后,请问哪个先执行?

错误答案:f2先执行
正确答案:谁先监听谁先执行

总结:这是一个特例
const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
const level2 = document.querySelector('.level3')
const level2 = document.querySelector('.level4')
const level2 = document.querySelector('.level5')
const level2 = document.querySelector('.level6')
const level2 = document.querySelector('.level7')

level7.addEventListener('click',()=>{
  console.log(2)
},true) //捕获

level7.addEventListener('click',()=>{
  console.log(1)
}) //冒泡 

四、取消冒泡

捕获不可取消,但冒泡可以

  • e.stopPropagation()可中断冒泡,浏览器不再向上走
  • 通俗来说:有人打我,我自己解决,别告诉我老子
  • 一般用于封装某些独立的组件

五、不可阻止默认动作

有些事件不能阻止默认动作

  • MDN搜索scroll event,看到Bubbles和Cancelable
  • Bubbles的意思是该事件是否冒泡,所有冒泡都可取消
  • Cancelable的意思是开发者是否可以阻止默认事件
  • Cancelable与冒泡无关

CSS也行

  • 使用overflow:hidden可以直接取消滚动条

  • 但此时JS依然可以修改scrollTop

小结

1、target和currentTarget

  • 一个是用户点击的,一个是开发者监听的

2、取消冒泡

  • e.stopPropagation()

3、事件的特性

  • Bubbles表示是否冒泡
  • Cancelable表示是否支持开发者取消冒泡
  • 如scroll不支持取消冒泡

4、如何禁用滚动

  • 取消特定元素的wheel和touchstart的默认动作