浅谈js事件机制

  • 事件是什么?
  • 事件模型?
    • 原始事件模型(DOM0级)
      • HTML代码中指定属性值:
      • 在js代码中指定属性值:
      • 优点:
      • 缺点:
    • IE 事件模型
    • DOM2事件模型
  • 对事件循环的理解
    • 宏任务(Macrotasks)
    • 微任务(Microtasks)
    • Event Loop 执行顺序如下所示:

事件是什么?

事件是 用户操作网页时发生的交互动作,比如 click/move, 事件除了用户触发的动作外,还可以是文档加载,窗口滚动和大小调整。

事件被 封装成一个 event 对象,包含了该事件发生时的所有相关信息( event 的属性)以及可以对事件进行的操作( event 的方法)。

事件模型?

JavaScript事件模型指的是一种基于事件驱动的编程模式,用于处理浏览器和用户发生的事件。当用户或浏览器执行某个动作时,例如点击某个元素或者提交表单,JavaScript就会将这些动作封装为一个事件,并将该事件传递给注册了该事件的回调函数。

JavaScript中的事件分为两种类型:

  • 原生事件
  • 自定义事件。

原生事件是由浏览器定义的事件,如点击、滚动、鼠标移动等,而自定义事件是由开发人员自己定义的事件。

在JavaScript事件模型中,当一个事件发生时,浏览器会将该事件封装成一个事件对象,并将其传递给注册了该事件的回调函数。

开发人员可以通过addEventListener()方法来向一个元素注册一个事件监听器,该方法接受三个参数:事件类型、回调函数和一个布尔值,指示回调函数是在事件捕获阶段还是事件冒泡阶段被调用。

事件捕获是从顶层元素开始,向下级元素逐层传递事件的过程,直到抵达目标元素。事件冒泡则是从目标元素开始,向上级元素逐层传递事件的过程,直到抵达顶层元素。开发人员可以根据需要选择事件捕获还是事件冒泡阶段来注册事件监听器。

在事件处理函数中,开发人员可以使用event对象来访问事件相关的信息,如事件类型、目标元素、鼠标位置等。同时,还可以通过event.preventDefault()方法来阻止默认行为,或通过event.stopPropagation()方法来阻止事件传播。

在JavaScript中,事件模型是一种非常重要的编程模式,可以帮助开发人员更好地处理用户交互、浏览器行为等方面的问题。

事件是用户操作网页时发生的交互动作或者网页本身的一些操作,现代浏览器一共有三种事件模型:

原始事件模型(DOM0级)

在原始事件模型中,事件发生后没有传播的概念,所以没有事件流的概念。

但是现在有的浏览器支持以冒泡的方式实现,它可以在网页中直接定义监听函数,也可以通过 js 属性来指定监听函数。

事件发生,马上处理。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。

直接在 dom 对象上注册事件名称,就是 DOM0 写法

书写方式有两种:

HTML代码中指定属性值:
<input type="button" onclick="func1()" />
在js代码中指定属性值:
document.getElementsByTagName(‘input’)[0].onclick = func1
优点:

所有浏览器都兼容

缺点:
  • 逻辑与显示没有分离;
  • 相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的,如:a.onclick = func1; a.onclick = func2;将只会执行func2中的内容;
  • 无法通过事件的冒泡、委托等机制完成更多事情;

IE 事件模型

“IE不把该对象传入事件处理函数,由于在任意时刻只会存在一个事件,所以IE把它作为全局对象window的一个属性”,用IE8执行了代码alert(window.event),结果弹出是null,说明该属性已经定义,只是值为null(与undefined不同),

代码如下:

window.onload = function (){alert(window.event);}

setTimeout(function(){alert(window.event);}2000);

第一次弹出【object event】,两秒后弹出依然是null。

由此可见IE是将event对象在处理函数中设为window的属性,一旦函数执行结束,便被置为null了;

在该事件模型中,一次事件共有两个过程:

  • 事件处理阶段(先执行元素的监听函数,)
  • 事件冒泡阶段(然后事件沿着父节点一直冒泡到document。)

事件处理阶段会首先执行目标元素绑定的监听事件。

然后是事件冒泡阶段,冒泡指的是事件从目标元素冒泡到document,依次检查经过的节点是否绑定了事件监听函数,如果有则
执行。

这种模型通过 attachEvent 来添加监听函数,可以添加多个监听函数,会按顺序依次执行。

IE模型下的事件监听方式比较独特,绑定监听函数的方法是:

attachEvent( "eventType""handler");//其中evetType为事件的类型,

如onclick,注意要加’on’。解除事件监听器的方法是:

detachEvent("eventType""handler" )

IE的事件模型已经可以解决原始模型的三个缺点,但其自己的缺点就是兼容性,只有IE系列浏览器才可以这样写。

更多详细内容,请微信搜索“前端爱好者戳我 查看

DOM2事件模型

此模型是W3C制定的标准模型,既然是标准,现代浏览器(指IE6~8除外的浏览器)都已经遵循这个规范。

W3C制定的事件模型中,一次事件的发生包含三个过程:

  • capturing phase:事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行;
  • target phase:事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数;
  • bubbling phase:事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行;

这种事件模型,事件绑定的函数是 addEventListener,其中第三个参数可以指定事件是否在捕获阶段执行。

所有的事件类型都会经历captruing phase但是只有部分事件会经历bubbling phase阶段,例如submit事件就不会被冒泡。

标准的事件监听器绑定:

addEventListener("eventType""handler""true|false");

其中eventType指事件类型。第二个参数是处理函数,第三个即用来指定是否在捕获阶段进行处理,一般设为false来与IE保持一致。

监听器的解除也类似:

removeEventListner("eventType""handler""true!false");

以上便是事件的三种模型,我们在开发的时候需要兼顾IE与非IE浏览器,所以注册一个监听器应该这样写:

var a = document.getElementById('a');
if(a.attachEvent){
    a.attachEvent('onclick',func);
}
else{
    a.addEventListener('click',func,false);
}

对事件循环的理解

因为 js 是单线程运行的,在代码执行时,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。

在执行同步代码时,如果遇到异步事件,js 引擎并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。

当异步事件执行完毕后,再将异步事件对应的回调加入到一个任务队列中等待执行。

任务队列可以分为:

  • 宏任务队列
  • 微任务队列

宏任务(Macrotasks)

宏任务(Macrotasks)包括以下几种常见的操作:

  1. setTimeout和setInterval: 通过定时器设置的回调函数会被添加到宏任务队列中,等待执行。

  2. I/O 操作:涉及到网络请求、文件读写等的异步操作会被添加到宏任务队列中。

  3. UI 渲染:渲染引擎会将UI渲染任务添加到宏任务队列中。

  4. 事件处理程序:例如点击事件、键盘事件等会触发相应的回调函数,这些回调函数也会被添加到宏任务队列中。

微任务(Microtasks)

微任务(Microtasks)则是具有更高优先级的异步操作,它们会在当前宏任务执行完毕后立即执行。

常见的微任务包括:

  1. Promise回调函数: 当Promise对象状态变为resolved或rejected时,相关的回调函数会被添加到微任务队列中。

  2. MutationObserver: 监听DOM树变化的回调函数会被添加到微任务队列中。

  3. process.nextTick(Node.js环境): 在Node.js环境中,process.nextTick函数添加的回调函数会被添加到微任务队列中。

对于执行顺序,当一个宏任务执行完毕后,会先执行所有的微任务队列中的任务,直到微任务队列为空,然后再执行下一个宏任务。这样的循环保证了微任务具有更高的优先级,能够及时处理一些重要的回调函数。

总结,

  • 宏任务包括定时器、I/O操作、UI渲染和事件处理程序等,
  • 而微任务包括Promise回调函数和MutationObserver等。

微任务比宏任务具有更高的优先级,在当前宏任务结束后立即执行。

当当前执行栈中的事件执行完毕后,js 引擎首先会判断微任务队列中是否有任务可以执行,如果有就将微任务队首的事件压入栈中执行。当微任务队列中的任务都执行完成后再去执行宏任务队列中的任务

Event Loop 执行顺序如下所示:

JavaScript中的Event Loop是用来管理异步代码执行的机制。

它确保了代码运行的顺序和正确性。下面是Event Loop的大致执行顺序:

  1. 执行同步代码:从上到下依次执行JavaScript代码中的同步部分。

  2. 处理微任务(Microtasks): 当遇到微任务时,会将微任务添加到一个微任务队列中。常见的微任务包括Promise回调函数、MutationObserver和process.nextTick。在当前宏任务执行完毕后,会依次执行微任务队列中的所有微任务,直到队列为空。

  3. 执行宏任务(Macrotasks): 当所有微任务执行完毕后,会检查是否有宏任务需要执行。常见的宏任务包括setTimeout、setInterval、requestAnimationFrame、I/O操作和事件回调。从宏任务队列中取出一个任务执行,执行完毕后返回步骤2。

  4. 重复步骤2和步骤3: 不断循环执行步骤2和步骤3,直到没有待处理的微任务和宏任务。

需要注意的是,微任务具有更高的优先级,会在下一个宏任务执行之前被处理完毕。而宏任务则是按照添加的顺序执行。

同时,值得提及的是,不同的宿主环境(例如浏览器和Node.js)可能有一些差异,但大致的执行逻辑是相似的。

Event Loop的执行顺序可以简化为:同步代码 -> 微任务 -> 宏任务 -> 重复执行微任务和宏任务

这样的循环保证了JavaScript的并发性和响应性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WSL安装Ubuntu22.04,以及深度学习环境的搭建

安装WSL 安装 WSL 2 之前&#xff0c;必须启用“虚拟机平台”可选功能。 计算机需要虚拟化功能才能使用此功能。 以管理员身份打开 PowerShell 并运行&#xff1a; dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart下载 Linux 内核更…

【开源】SpringBoot框架开发服装店库存管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 服装档案模块2.4 服装入库模块2.5 服装出库模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 服装档案表3.2.3 服装入库表3.2.4 服装出库表 四、系统展示五、核心代码5.…

C++学习Day05之递增运算符重载

目录 一、程序及输出1.1 前置重载1.2 后置重载 二、分析与总结 一、程序及输出 1.1 前置重载 #include<iostream> using namespace std;class MyInter {friend ostream& operator<<(ostream& cout, MyInter& myInt); public:MyInter(){m_Num 0;}//前…

CSS 圆形的时钟秒针状的手柄绕中心点旋转的效果

<template><!-- 创建一个装载自定义加载动画的容器 --><view class="cloader"><!-- 定义加载动画主体部分 --><view class="clface"><!-- 定义类似秒针形状的小圆盘 --><view class="clsface"><!-…

实战打靶集锦-024-Seppuku

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 FTP探查4.2 80端口探查4.3 探查smb4.4 探查7080端口httpd4.5 探查Apache4.6 探查8088端口的LiteSpeed4.7 大海捞…

【自然语言处理】:实验4布置,预训练语言模型实现与应用

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c;自然语言处理专栏持续更新中&#xff0c;期待的小伙伴敬请关注 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 案例简介 2018年&#xff0c;Google提出了预训练语言模型BE…

深度学习之pytorch实现线性回归

度学习之pytorch实现线性回归 pytorch用到的函数torch.nn.Linearn()函数torch.nn.MSELoss()函数torch.optim.SGD() 代码实现结果分析 pytorch用到的函数 torch.nn.Linearn()函数 torch.nn.Linear(in_features, # 输入的神经元个数out_features, # 输出神经元个数biasTrue # 是…

Android 发布蒲公英平台自动更新

蒲公英官网&#xff1a;https://www.pgyer.com/ 首先弄明白蒲公英平台的SDK更新机制&#xff1a;蒲公英 - 文档中心 - SDK 自动更新机制 (pgyer.com) 下面直接开始代码操作 1.添加蒲公英maven库 maven { url "https://raw.githubusercontent.com/Pgyer/mvn_repo_pgyer…

Matlab论文插图绘制模板第136期—极坐标气泡图

在之前的文章中&#xff0c;分享了Matlab笛卡尔坐标系的气泡图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下极坐标气泡图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需要的朋…

基于微信小程序的校园跑腿系统的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

threehit漏洞复现以及防御

说白了跟sql-liql靶场二次注入一样&#xff0c;也是一个转义函数而这次是&#xff0c;入库的时候不转义&#xff0c;出库的时候会转义导致这个漏洞出现 开始测试&#xff1a; 这是我注册完test刚登录的情况 找注入点更新数据的update&#xff0c;很容易找到在age段 这次我注册…

12.QT文件对话框 文件的弹窗选择-QFileDialog

目录 前言&#xff1a; 技能&#xff1a; 内容&#xff1a; 1. 界面 2.信号槽 3.其他函数 参考&#xff1a; 前言&#xff1a; 通过按钮实现文件弹窗选择以及关联的操作 效果图就和平时用电脑弹出的选文件对话框一样 技能&#xff1a; QString filename QFileDialog::ge…

(九)【Jmeter】线程(Threads(Users))之bzm-Free-Form Arrivals Thread Group

简述 操作路径如下: 作用:支持自由形式的用户到达模式,具有更高的灵活性,与Arrivals Thread Group类似,不过是通过设置起始值、终止值和持续时间来达到压测目的。配置:通过图形界面或脚本定义用户到达曲线。使用场景:模拟复杂的用户到达模式,满足特定业务需求。优点:…

第三百五十三回

文章目录 1. 概念介绍2. 使用方法2.1 获取所有时区2.2 转换时区时间 3. 示例代码4. 内容总结 我们在上一章回中介绍了"分享一些好的Flutter站点"相关的内容&#xff0c;本章回中将介绍timezone包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

open3d k-means 聚类

k-means 聚类 一、算法原理1、介绍2、算法步骤 二、代码1、机器学习生成kmeans聚类2、点云学习生成聚类 三、结果1、原点云2、机器学习生成kmeans聚类3、点云学习生成聚类 四、相关链接 一、算法原理 1、介绍 K-means聚类算法是一种无监督学习算法&#xff0c;主要用于数据聚…

扩展语音识别系统:增强功能与多语言支持

一、引言 在之前的博客中&#xff0c;我们成功构建了一个基于LibriSpeech数据集的英文语音识别系统。现在&#xff0c;我们将对系统进行扩展&#xff0c;增加一些增强功能&#xff0c;并尝试支持多语言识别。 二、增加增强功能 语音合成 --除了语音识别&#xff0c;我们还可以…

SpringMVC的执行流程

过去的开发中,视图阶段&#xff08;老旧JSP等&#xff09; 1.首先用户发送请求到前端控制器DispatcherServlet(这是一个调度中心) 2.前端控制器DispatcherServlet收到请求后调用处理器映射器HandlerMapping 3.处理器映射器HandlerMapping找到具体的处理器,可查找xml配置或注…

简单理解VQGAN

简单理解VQGAN TL; DR&#xff1a;与 VQVAE 类似&#xff0c;隐层压缩表征自回归生成的两阶段图像生成方法。增加感知损失和对抗损失&#xff0c;提高压缩表征模型解码出图片的清晰度。还可以通过编码并预置条件表征&#xff0c;实现条件生成。 隐层压缩表征自回归生成&#…

迁移SVN和GIT的云端数据

在新服务器搭建GIT仓库 教程很多&#xff0c;大致的流程是&#xff1a; 1. 新建linux用户密码专用于git操作 2. 新建git库的存放文件夹并在此初始化git 3. 配置git库所在目录权限 *只需要有一个库和有一个用户&#xff0c;与在windows上建库是一样的。不需要搭建类似gitla…

深入解析Android AIDL:实现跨进程通信的利器

深入解析Android AIDL&#xff1a;实现跨进程通信的利器 1. 介绍Android AIDL Android Interface Definition Language (AIDL) 是一种Android系统中的跨进程通信机制。AIDL允许一个应用程序的组件与另一个应用程序的组件通信&#xff0c;并在两者之间传输数据。 AIDL的主要作…