【查漏补缺系列-DOM篇】浏览器事件模型

前言: 本类文章初衷只用作记录个人的学习博客,哪里有漏补哪里,不做任何其他商业用途。欢迎讨论,不喜勿喷。后面要是有遗漏的相关知识点,也会相应的补上。如果本篇文章能帮到你,我也会很愉快,共勉😁

目录

  1. 事件绑定
  2. 事件冒泡与捕获
  3. 事件委托
  4. 阻止事件冒泡
  5. 阻止默认事件

事件绑定

要想让Javascript对用户的操作做出响应,首先要对DOM元素绑定事件处理函数。

  • 在DOM元素中直接通过事件名绑定事件处理函数;
  • 在js中通过直接赋值的方式绑定事件处理函数;
  • addEventListener事件监听函数;

DOM元素中的事件绑定

js 复制代码
      function show() {
        console.log('show')
      }

      function hide() {
        console.log('hide')
      }

在html的事件中可以绑定一个或多个事件

html 复制代码
    <!-- show -->
    <button onclick="show()">绑定一个函数</button>

    <!-- hide show -->
    <button onclick="hide();show()">绑定多个函数</button>

直接为对应的事件赋值绑定函数

通过直接赋值的方式绑定无法绑定多个函数,后面绑定的会覆盖前面

js 复制代码
  // hide会覆盖show
  document.querySelectorAll('button')[0].onclick = show;
  document.querySelectorAll('button')[0].onclick = hide;

绑定事件监听函数

js 复制代码
    // show和hide都会触发
    document.querySelectorAll('button')[0].addEventListener('click', show, {})
    document.querySelectorAll('button')[0].addEventListener('click', hide, {})

    // 移除事件监听
    document.querySelectorAll('button')[0].removeEventListener('click', show)

# EventTarget:addEventListener参数详解

事件冒泡与捕获

事件冒泡

当某元素执行某一种类型事件,那么从该元素起逐级向外层的元素检测是否存在与本身同样的事件。这一个过程,就叫做事件冒泡(从内向外)。

html 复制代码
  <div class="box box1">
    box1
    <div class="box box2">
      box2
      <div class="box box3">box3</div>
    </div>
  </div>

当点击box3时,事件会向上逐级冒泡,依次触发box2和box1,所以打印顺序是3 2 1

js 复制代码
const boxList = document.querySelectorAll('.box');

[...boxList].forEach((item, index) => {
  item.addEventListener('click', () => {
    console.log(`${index + 1}`) // 3 2 1
  }, false)
})

事件冒泡的机制:浏览器会从box3的父元素身上找同类型事件(click),如果找到了则触发并再次向上传递(无论有没有找到都会继续向上传递),直到document为止。

事件捕获

事件捕获:当元素被触发事件时,从该元素的根节点(document)开始逐级向里寻找同类型事件,直到目标元素为止。这个过程就被称为事件捕获。

addEventlistener的第三个参数改为true则调整为事件捕获模式。此时会从最外层逐层向下寻找同类型事件,最终到目标元素。中途会依次触发相应的click事件,所以打印顺序是 1 2 3

js 复制代码
[...boxList].forEach((item, index) => {
  item.addEventListener('click', () => {
    console.log(`${index + 1}`) // 1 2 3
  }, true)
})

事件委托

事件委托:把一个元素响应事件的函数委托到另一个元素(通常是委托到它的父层或者更外层元素上,真正绑定事件的是外层元素),当事件响应到需要绑定的元素时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。

事件模型分为三个阶段:

  • 捕获阶段:事件的触发响应从最顶层(document)到目标元素;
  • 目标阶段:事件响应到触发事件的最底层元素上;
  • 冒泡阶段:事件的触发响应从目标元素到最顶层(document);

假设我们的需求是每个li点击后都能打印出里面的内容:

html 复制代码
<ul>
    <li>javascript</li>
    <li>vue</li>
    <li>react</li>
    <li>svelte</li>
</ul>

不使用事件委托,循环遍历所有li节点并依次绑定事件,这样可以做到,但会带来以下几个问题:

  1. 需要遍历所有的li节点并依次绑定事件(假如li节点特别多呢),对于内存消耗较大,效率较低。
  2. 如果li的节点在初始化之后,又再次动态插入了新的li节点,则又需要重新去编写相应的逻辑。
js 复制代码
const lis = document.querySelectorAll('li');
lis.forEach((item) => {
  item.addEventListener('click', (e) => console.log(e.target.innerText));
})

使用事件委托,只需要将点击事件绑入外层元素(如ul)中,在用户点击相应的li时,借由冒泡的事件机制即可定位到指定li。

js 复制代码
const ul = document.querySelector('ul');
ul.addEventListener('click', (e) => console.log(e.target.innerText), false);

阻止事件冒泡

阻止事件冒泡/捕获

js 复制代码
    function stopBubble(e) {
      // 非IE浏览器
      if (e && e.stopPropagation) {
        e.stopPropagation();
      } else {
        // 兼容IE
        window.event.cancelBubble = true
      }
    }

阻止默认事件

阻止默认事件阻止就是某些元素自带的默认行为,如果元素本身没有默认行为,调用自然就无效了。拥有默认行为的元素如<a href=""><input type="sumbit">等。

js 复制代码
    function preventDefault() {
      // 非IE浏览器
      if (e && e.preventDefault) {
        e.preventDefault();
      } else {
        // 兼容IE
        window.event.returnValue = true
      }
    }
相关推荐
MiyueFE29 分钟前
14 个逻辑驱动的 UI 设计技巧,助您改善任何界面
前端·设计
啃火龙果的兔子33 分钟前
前端单元测试覆盖率工具有哪些,分别有什么优缺点
前端·单元测试
「、皓子~1 小时前
后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端+前端
前端·人工智能·微服务·小程序·go·ai编程·ai写作
就改了1 小时前
Ajax——在OA系统提升性能的局部刷新
前端·javascript·ajax
凌冰_1 小时前
Ajax 入门
前端·javascript·ajax
京东零售技术1 小时前
京东小程序JS API仓颉改造实践
前端
老A技术联盟1 小时前
从小白入门,基于Cursor开发一个前端小程序之Cursor 编程实践与案例分析
前端·小程序
风铃喵游2 小时前
构建引擎: 打造小程序编译器
前端·小程序·架构
sunbyte2 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟2 小时前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计