JavaScrpt_11 Web API 事件流、委托事件、其它事件、元素尺寸与位置

news2024/11/14 22:08:04

JavaScrpt_11 Web API 事件流、委托事件、其它事件、元素尺寸与位置

  • 前言
  • 一、事件流
    • 1. 捕获和冒泡
    • 2. 阻止冒泡
  • 二、委托事件
  • 三、其它事件
    • 1. 页面加载事件
    • 2. 元素滚动事件
    • 3. 页面尺寸事件
  • 四、元素尺寸与位置


前言

进一步学习 事件进阶,实现更多交互的网页特效,结合事件流的特征优化事件执行的效率

  • 掌握阻止事件冒泡的方法
  • 理解事件委托的实现原理

一、事件流

事件流是对事件执行过程的描述,了解事件执行过程有助于加深对事件的理解,提升开发中对事件的运用的灵活度。
在这里插入图片描述
如上图所示,任意事件被触发时总会经历两个阶段:【捕获阶段】和【冒泡阶段】。

简言之,捕获阶段是【从父到子】的传导过程,冒泡阶段是【从子向父】的传导过程。

1. 捕获和冒泡

了解了什么是事件流之后,我们来看事件流是如何影响事件执行的:

<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer');
    const inner = document.querySelector('.inner');
    const child = document.querySelector('.child');
		
    // html 元素添加事件
    document.documentElement.addEventListener('click', function () {
      console.log('html...')
    })
		
    // body 元素添加事件
    document.body.addEventListener('click', function () {
      console.log('body...')
    })

    // 外层的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('outer...')
    })
    
    // 中间的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('inner...')
    })
    
    // 内层的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('child...')
    })
  </script>
</body>

执行上述代码后发现,当单击事件触发时,其祖先元素的单击事件也【相继触发】,这是为什么呢?

结合事件流的特征,我们知道当某个元素的事件被触发时,事件总是会先经过其祖先才能到达当前元素,然后再由当前元素向祖先传递,事件在流动的过程中遇到相同的事件便会被触发

再来关注一个细节就是事件相继触发的【执行顺序】,事件的执行顺序是可控制的,即可以在捕获阶段被执行,也可以在冒泡阶段被执行。

如果事件是在冒泡阶段执行的,我们称为冒泡模式,它会先执行子盒子事件再去执行父盒子事件,默认是冒泡模式。

如果事件是在捕获阶段执行的,我们称为捕获模式,它会先执行父盒子事件再去执行子盒子事件。

捕获模式:

<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner"></div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')

    // 外层的盒子
    outer.addEventListener('click', function () {
      console.log('outer...')
    }, true) // true 表示在捕获阶段执行事件
    
    // 中间的盒子
    outer.addEventListener('click', function () {
      console.log('inner...')
    }, true)
  </script>
</body>

结论:

  1. addEventListener 第3个参数决定了事件是在捕获阶段触发还是在冒泡阶段触发
  2. addEventListener 第3个参数为 true 表示捕获阶段触发,false 表示冒泡阶段触发,默认值为 false
  3. 事件流只会在父子元素具有相同事件类型时才会产生影响
  4. 绝大部分场景都采用默认的冒泡模式(其中一个原因是早期 IE 不支持捕获)

2. 阻止冒泡

阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。

<body>
  <h3>阻止冒泡</h3>
  <p>阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')
    const child = document.querySelector('.child')

    // 外层的盒子
    outer.addEventListener('click', function () {
      console.log('outer...')
    })

    // 中间的盒子
    inner.addEventListener('click', function (ev) {
      console.log('inner...')

      // 阻止事件冒泡
      ev.stopPropagation()
    })

    // 内层的盒子
    child.addEventListener('click', function (ev) {
      console.log('child...')

      // 借助事件对象,阻止事件向上冒泡
      ev.stopPropagation()
    })
  </script>
</body>

结论:事件对象中的 ev.stopPropagation 方法,专门用来阻止事件冒泡。

鼠标经过事件:

mouseover 和 mouseout 会有冒泡效果

mouseenter 和 mouseleave 没有冒泡效果 (推荐)

二、委托事件

事件委托是利用事件流的特征解决一些现实开发需求的知识技巧,主要的作用是提升程序效率。
大量的事件监听是比较耗费性能的,如下代码所示

<script>
  // 假设页面中有 10000 个 button 元素
  const buttons = document.querySelectorAll('table button');

  for(let i = 0; i <= buttons.length; i++) {
    // 为 10000 个 button 元素添加了事件
    buttons.addEventListener('click', function () {
      // 省略具体执行逻辑...
    })
  }
</script>

利用事件流的特征,可以对上述的代码进行优化,事件的冒泡模式总是会将事件流向其父元素的,如果父元素监听了相同的事件类型,那么父元素的事件就会被触发并执行,正是利用这一特征对上述代码进行优化,如下代码所示:

<script>
  // 假设页面中有 10000 个 button 元素
  let buttons = document.querySelectorAll('table button');
  
  // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
  let parents = document.querySelector('table');
  parents.addEventListener('click', function () {
    console.log('点击任意子元素都会触发事件...');
  })
</script>

我们的最终目的是保证只有点击 button 子元素才去执行事件的回调函数,如何判断用户点击是哪一个子元素呢?
在这里插入图片描述
事件对象中的属性 targetsrcElement属性表示真正触发事件的元素,它是一个元素类型的节点。

<script>
  // 假设页面中有 10000 个 button 元素
  const buttons = document.querySelectorAll('table button')
  
  // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
  const parents = document.querySelector('table')
  parents.addEventListener('click', function (ev) {
    // console.log(ev.target);
    // 只有 button 元素才会真正去执行逻辑
    if(ev.target.tagName === 'BUTTON') {
      // 执行的逻辑
    }
  })
</script>

优化过的代码只对祖先元素添加事件监听,相比对 10000 个元素添加事件监听执行效率要高许多!!!

三、其它事件

1. 页面加载事件

加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

有些时候需要等页面资源全部处理完了做一些事情

事件名:load

监听页面所有资源加载完毕:

window.addEventListener('load', function() {
    // xxxxx
})

2. 元素滚动事件

滚动条在滚动的时候持续触发的事件

window.addEventListener('scroll', function() {
    // xxxxx
})

3. 页面尺寸事件

会在窗口尺寸改变的时候触发事件:

window.addEventListener('resize', function() {
    // xxxxx
})

四、元素尺寸与位置

获取元素的自身宽高、包含元素自身设置的宽高、padding、border

offsetWidth和offsetHeight

获取出来的是数值,方便计算

注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手写CDN基本原理

本文已收录于专栏 《中间件合集》 目录 追本溯源概念说明需求分析核心功能代码实现A用户模块本地DNS模块CDN服务模块缓存服务模块原服务端 总结提升 追本溯源 CDN的发展源于对互联网内容传输速度和用户体验的需求。在互联网发展初期&#xff0c;内容的传输主要依赖于源服务器&a…

Unity/Shader 零碎知识点

坐标系 Unity使用的是左手坐标系&#xff1b;观察空间&#xff0c;通俗来讲就是以摄像机为原点的坐标系&#xff0c;摄像机的前向是z轴的负方向&#xff0c;与模型和世界空间中的定义相反&#xff0c;z轴的坐标减少意味着场景深度的增加 点积 abba|a||b|cos<a,b> 结果为常…

联想ThinkPad如何用U盘重装系统?联想ThinkPad用U盘重装系统教程

联想ThinkPad如何用U盘重装系统&#xff1f;当联想ThinkPad出现系统问题或需要更新操作系统时&#xff0c;使用U盘进行重装是一种快速而可靠的解决方案&#xff0c;使用U盘重装系统不仅简单易行&#xff0c;还能有效避免出现磁盘损坏或网络不稳定所带来的问题&#xff0c;那具体…

零零信安-DD数据泄露报警日报【第203期】

2023.07.10共发现匿名网络资讯信息83,544条&#xff1b;最近7天同比增长-22.2%&#xff1b;最近30天共发现匿名网络资讯信息2,578,034条。 北京零零信安科技有限公司成立于2020年&#xff0c;是国内首家专注于外部攻击面管理&#xff08;EASM&#xff09;的网络安全公司。基于…

DragGAN 离线版V1.3 解压就能用-DragGAN Windows GUI

一、DragGAN是什么 DragGAN是由Max Planck研究所开发的一种新的人工智能工具&#xff0c;它允许用户通过几个点击和拖动来真实地修改照片。DragGAN模型本质上是给各种GAN开发的一种交互式图像操作方法&#xff0c;实现了通过鼠标拉伸图像即可自动生成新图像的神奇功能。用户先…

Shader Graph22-卡通风格(上)

一、打开Unreal&#xff0c;新建Material命名为DemoToonPaint。 二、0.5、0.5、0.5为模拟的光线方向&#xff0c;VertexNormalWS为法线的世界坐标&#xff0c;Dot点积之后得到指定光线方向分布&#xff0c;Multiply(,0.5)和Add(,0.5)是去掉负值。Texture我们需要用photoshop制作…

flutter开发实战-长链接WebSocket使用stomp协议stomp_dart_client

flutter开发实战-长链接WebSocket使用stomp协议stomp_dart_client 在app中经常会使用长连接进行消息通信&#xff0c;这里记录一下基于websocket使用stomp协议的使用。 一、stomp&#xff1a;流文本定向消息协议 1.1 stomp介绍 stomp&#xff0c;Streaming Text Orientate…

chatGLM2中的Multi Query Attention

目录 原理简介 代码实现和耗时比较 总结分析 近期一直在玩大模型&#xff0c;对中文支持比较好的就是清华的chatGLM&#xff0c;目前chatGLM由v1升级到了chatGLM2。在gihub上介绍信息如下&#xff1a; 试用了一下&#xff0c;效果和速度确实有所提升。 这个得益于chatGLM2应…

pnpm + workspace + changesets

pnpm workspace changesets 构建你的 monorepo 工程 什么是monorepo&#xff1f; 什么是 monorepo&#xff1f;以及和 multirepo 的区别是什么? 关于这些问题&#xff0c;在之前的一篇**介绍 lerna** 的文章中已经详细介绍过&#xff0c;感兴趣的同学可以再回顾下。 简而…

nacos学习积累

官方文档&#xff1a;https://nacos.io/zh-cn/docs/quick-start.html 1 注册中心简介 注册中心对比和选型&#xff1a;Zookeeper、Eureka、Nacos、Consul和ETCD 如果消费者直接连接的提供者。这样做的问题是&#xff0c;若提供者出现宕机&#xff0c;或消费者存在高并发情况&…

SSRF漏洞

前言 作者简介&#xff1a;不知名白帽&#xff0c;网络安全学习者。 博客主页&#xff1a;不知名白帽的博客_CSDN博客-网络安全,CTF,内网渗透领域博主 网络安全交流社区&#xff1a;https://bbs.csdn.net/forums/angluoanquan 目录 SSRF漏洞原理 产生CSRF的函数 SSRF中常见手…

MySQL原理探索——27 主库出问题了,从库怎么办

在前面的第24、25和26篇文章中&#xff0c;介绍了 MySQL 主备复制的基础结构&#xff0c;但这些都是一主一备的结构。 大多数的互联网应用场景都是读多写少&#xff0c;因此你负责的业务&#xff0c;在发展过程中很可能先会遇到读性能的问题。而在数据库层解决读性能问题&#…

Atlassian Bamboo Enterprise Crack

Atlassian Bamboo Enterprise Crack Bamboo Server是专业组织如持续集成、安装和运输的选择。 从代码到安装的连续运输。 在一个工作流中集中发布自动生成、测试和发布。 构建&#xff1a;专注于编码&#xff0c;依靠Bamboo作为自己的CI&#xff0c;构建一个主机!创建多阶段构建…

3.8.cuda运行时API-使用cuda核函数加速yolov5后处理

目录 前言1. Yolov5后处理2. 后处理案例2.1 cpu_decode2.2 gpu_decode 总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习精简…

【*2200线段树Pushup】CF1567 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 维护这些信息即可 Code&#xff1a; #include <bits/stdc.h>#define int long longusing namespace std;const int mxn2e510; const int mxe2e510; const int mod1e97; const int Inf1e18;struct info{in…

【C语言】gcc编译时报错 fatal error: stdio.h: 没有那个文件或目录

零、问题 在Ubuntu20.04.6中使用GCC编译一个HelloWorld代码时遇到如下问题&#xff1a; 首先确认了&#xff0c;自己单词没有拼写错。 然后再检查GCC的版本&#xff0c;确实没问题&#xff1a; 我用的是Ubuntu20.04.6的版本。 壹、解决 没有标准的头文件需要安装build-es…

和鲸社区数据分析每周挑战【第九十七期:技术博客文本分析】

和鲸社区数据分析每周挑战【第九十七期&#xff1a;技术博客文本分析】 文章目录 和鲸社区数据分析每周挑战【第九十七期&#xff1a;技术博客文本分析】一、背景描述二、数据说明三、问题描述四、数据导入五、数据探索性分析六、对文章标题进行文本分类预测1、数据预处理2、逻…

C++万字自学笔记

[TOC] 一、 C基础 C的IDE有CLion、Visual Studio、DEV C、eclipse等等&#xff0c;这里使用CLion进行学习。 0. C初识 0.1 第一个C程序 编写一个C程序总共分为4个步骤 创建项目创建文件编写代码运行程序 #include <iostream>int main() {using namespace std;cout…

新手如何快速安装电脑监控软件?

越来越多的管理者选择使用电脑监控软件&#xff0c;许多新手不知道具体怎样安装&#xff0c;本期将为大家介绍下具体的安装流程。 电脑监控软件购买之后&#xff0c;会提供网址和账号密码&#xff0c;登录后需要先添加员工信息&#xff0c;有三种方法&#xff1a; &#xff0…

Android性能优化(bin启动优化)

我们平时会在android里面写个bin程序来干点活&#xff0c;但是有时候我们会发现很奇怪的现象&#xff0c;我明明很早就启动这个bin了&#xff0c;但是过了很久bin程序的main函数才被调用~。这个是为啥呢&#xff1f;主要有2个原因&#xff1a; 一.bin程序依赖的so库太多&#…