DOM 事件模型或 DOM 事件机制

简介: DOM 事件模型或 DOM 事件机制

DOM 事件模型或 DOM 事件机制


引入

1.点击事件

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

以上代码即.爷爷>.爸爸>.儿子

给三个div分别添加事件监听 fnYe / fnBa / fnEr。点击谁监听谁 问题一:

  • 点击文字,算不算点击儿子?
  • 点击文字,算不算点击爸爸?
  • 点击文字,算不算点击爷爷?

答案:都算

问题二: 调用监听函数顺序是什么呢

事件捕获:fnYe > fnBa > fnEr , 也就是从外到内去调用

事件冒泡:fnEr > fnBa > fnYe , 也就是从内到外去调用

2.和事佬W3C

2002年,W3C发布标准

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

一、DOM 事件机制

事件捕获和事件冒泡

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

疑问:从外到内再从内到外,那岂不是fnYe / fnBa / fnEr都调用两次?

  • 非也!开发者自己选择把fnYe放在捕获阶段还是放在冒泡阶段

示意图

网络异常,图片无法展示
|

如何指定走捕获还是冒泡呢?

baba.attachEvent('onclick',fn)//冒泡
baba.addEventListener('click',fn)//捕获
baba.addEventListener('click',fn,bool)//w3c制定
  • 如果bool不传或为falsy
  • 就让fn走冒泡,即当浏览器在冒泡阶段发现 babafn 监听函数,就会调用fn,并提供事件信息。
  • 如果bool为true
  • 就让fn走捕获,即当浏览器在捕获阶段发现 babafn 监听函数,就会调用fn,并且提供事件信息。

一个特例

//只有一个 div 被监听(不需要考虑父子关系)
div.addEventListenter('click',f1) //冒泡
div.addEventListenter('click',f2,true) //捕获

f1 先执行还是 f2 先执行呢?

先捕获在冒泡, f2 先执行?

正确答案:f1 先执行。

当没有父子关系时,谁先监听谁就先执行。

target 与 currentTarget的区别

  • e.target 用户操作的元素
  • e.currentTarget 程序员监听的元素

例子:

<div>
  <span>文字</span>
</div>
  • e.target 就是 span ,用户操作的元素。
  • e.currentTarget 就是 div , 程序员监听的元素。

取消冒泡

e.stopPropagation() 可打断冒泡,浏览器不再向上走

一般用于封装某些独立组件

注意:捕获不可以取消但是冒泡可以(有些事件也不能够取消冒泡,例如: scroll 滚动条)

不可阻止默认动作

  • 有些事件不能 
  • MDN搜索scroll event,看到Bubbles和 Cancelable
  • Bubbles的意思是该事件是否冒泡,所有冒泡都可取消
  • Cancelable的意思是开发者是否可以阻止默认事件
  • Cancelable与冒泡无关
  • 推荐看MDN英文版,中文版内容不全
  • 如何阻止滚动

1.scroll 事件不可阻止默认动作

  • 阻止scroll默认动作没用,因先有滚动才有滚动事件
  • 要阻止滚动,可阻止 wheel和 touchstart的默认动作
  • 注意你需要找准滚动条所在的元素,示例
  • 但是滚动条还能用,可用CSS让滚动条width: 0 (::-webkit-scrollbar { width: 0 !important })

2.CSS也行

  • 使用overflow: hidden可以直接取消滚动条
  • 但此时JS依然可以修改scrollTop

小结

  • target和currentTarget
  • 一个是用户点击的,一个是开发者监听的
  • 取消冒泡
  • e.stopPropagation()
  • 事件的特性
  • Bubbles表示是否冒泡
  • Cancelable表示是否支持开发者取消冒
  • 如scroll不支持取消冒泡
  • 如何禁用滚动
  • 取消特定元素的wheel和touchstart的默认动作

自定义事件

-自定义事件

  • 浏览器自带事件
  • 一共100多种事件,列表在MDN 上
  • 提问
  • 开发者能不能在自带事件之外,自定义一个事件
  • 答案:可以,见示例

二、事件委托

1.什么是事件委托

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。通俗地来讲,就是把一个元素响应事件(click、......)的函数委托到另一个元素; 一般来说,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。

2.常见应用场景

场景一

  • 你要给100个按钮添加点击事件,咋办?
  • 答:监听这100个按钮的祖先,等冒泡的时候判断target是不是这100个按钮中的一个代码示例

场景二

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

优点

  • 省监听数(内存)
  • 可以监听动态元素

3. 代码实现

需求:监听所有的 li 标签,如果用户点击 li 标签,就 console.log('用户点击了 Li 标签')

<ul id="test">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

那么实现的 JS 代码就是:

// 监听父元素 ul#test
test.addEventListener('click', (e)=> {
  //通过浏览器传进来的e参数,找到当前点击元素
  const t = e.target
  // 判断当前元素是不是Li标签
  if(t.matches('li') {
    console.log('用户点击了li')
  }
})

实现思路:

  1. 首先监听父元素,
  2. 然后根据浏览器传进去的事件信息,拿到当前点击元素,
  3. 再判断当前点击元素是不是 li 元素, 如果是,就 console.log('用户点击 Li 标签')

基于此,我们可以封装一个事件委托函数

on("click", "#test", "li", () => {
  console.log("用户点击了li");
});
function on(eventType, parentElement, selector, fn) {
  // 先判断是不是element,
  //如果传进来的是选择器,不是element本身,就先变成element,
  // 因为只有element才能监听事件
  if (!(parentElement instanceof Element)) {
    parentElement = parentElement.querySelectorAll(parentElement);
  }
  parentElement.addEventListener(eventType, (e) => {
    let target = e.target;
    if (target.matches(selector)) {
      fn(e);
    }
  });
}

但是以上这种实现有一个小问题,那就是如果被点击元素有多个父元素怎么办?

<ul id="test">
  <li>
    <p>
      <span>1</span>
    </p>
  </li>
  <li>
    <p>
      <span>2</span>
    </p>
  </li>
  <li>
    <p>
      <span>3</span>
    </p>
  </li>
  <li>
    <p>
      <span>4</span>
    </p>
  </li>
</ul>

我们需要做的就是: 递归地向上多找几层父节点,直到找到 li 标签,

同时还必须限定,寻找的范围不能超过 parentElement,

拿上面的例子来说,不可以越过 ul 标签,去找 body 标签

on("click", "#test", "li", () => {
  console.log("用户点击了li");
});
function on(eventType, element, selector, fn) {
  if (!(element instanceof Element)) {
    element = document.querySelectorAll(element);
  }
  element.addEventListener(eventType, (e) => {
    let target = e.target;
    // 如果匹配到了selector就跳出循环
    while (!target.matches(selector)) {
      if (target === element) {
        //已经找到了父元素,说明还没找到,就设置为null
        target = null;
        break;
      }
      target = target.parentNode;
    }
    // 找到了target, 就调用函数
    target && fn.call(target, e);
  });
}

三、总结

1.捕获和冒泡

捕获:当用户点击按钮,浏览器会从 window 从上向下遍历至用户点击的按钮,逐个触发事件处理函数。

冒泡:浏览器从用户点击的按钮从下往上遍历至 window,逐个触发事件处理函数。

网络异常,图片无法展示
|

什么是事件委托

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。通俗地来讲,就是把一个元素响应事件(click、......)的函数委托到另一个元素; 一般来说,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。

相关文章
|
JavaScript 前端开发 算法
MVVM模型,虚拟DOM和diff算法
1.MVVM是前端开发领域当中非常流行的开发思想。(一种架构模式)目前前端的大部分主流框架都实现了这个MVVM思想,例如Vue,React等2.虽然Vue没有完全遵循MVVM模型,但是Vue的设计也受到了它的启发。Vue框架基本上也是符合MVVM思想的 3.MVVM模型当中尝到了Model和View进行了分离,为什么要分离?
|
XML 消息中间件 JavaScript
从0开始学习JavaScript--JavaScript DOM操作与事件处理
在前端开发中,DOM(文档对象模型)是一个至关重要的概念,它为JavaScript提供了一种与HTML和XML文档交互的方法。本文将深入探讨DOM的概念与作用,以及JavaScript与DOM之间的密切关系。
|
XML 编解码 JavaScript
DOM(文档对象模型)和 BOM(浏览器对象模型)
【10月更文挑战第19天】在前端开发中,理解 DOM(文档对象模型)和 BOM(浏览器对象模型)是至关重要的。它们是 Web 开发的基础,为我们提供了与网页文档和浏览器进行交互的能力。
1394 62
|
12月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
433 5
|
JavaScript 前端开发
JavaScript HTML DOM 事件
JavaScript HTML DOM 事件
108 5
|
JavaScript 前端开发
js之DOM 文档对象模型
js之DOM 文档对象模型
103 1
js之DOM 文档对象模型
|
前端开发 JavaScript
CSS中禁用DOM事件
CSS中禁用DOM事件
|
JavaScript 前端开发 API
深入理解jQuery:高效DOM操作与事件处理
【10月更文挑战第11天】深入理解jQuery:高效DOM操作与事件处理
164 0
|
JavaScript 前端开发
js之DOM 文档对象模型
js之DOM 文档对象模型
|
XML 存储 JavaScript
DOM(文档对象模型):理解网页结构与内容操作的关键技术
**DOM摘要:**文档对象模型(DOM)是独立于语言的接口,用于访问和修改HTML或XML文档。HTML DOM用于HTML,XML DOM用于XML。示例展示了如何用JavaScript通过DOM获取和修改元素,如通过ID或标签名。XML DOM涉及加载XML文件或字符串,获取元素值。DOM节点包括文档、元素、文本等,通过属性(如nodeName, nodeValue)和方法(如getElementsByTagName, appendChild)操作。节点树结构允许遍历和修改文档结构。
181 2
DOM(文档对象模型):理解网页结构与内容操作的关键技术