浅谈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的并发性和响应性。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机构vip教程】Android SDK手机测试环境搭建

Android SDK 的安装和环境变量的配置 前置条件&#xff1a;需已安装 jdk1.8及 以上版本 1、下载Android SDK&#xff0c;解压后即可&#xff08;全英文路径&#xff09;&#xff1b;下载地址&#xff1a;http://tools.android-studio.org/index.php/sdk 2、新建一个环境变量&…

【教程】Kotlin语言学习笔记(一)——认识Kotlin(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 文章目录 【Kotlin语言学习】系列文章一、Kotlin介绍二、学习路径 一、…

在职阿里6年,一个28岁女软件测试工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;16届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09; 其中成功的有4家&am…

阿里云香港轻量应用服务器怎么样,建站速度快吗?

阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品&#xff0c;中国电信CN2高速网络高质量、大规格BGP带宽&#xff0c;运营商精品公网直连中国内地&#xff0c;时延更低&#xff0c;优化海外回中国内地流量的公网线路&#xff0c;可以提高国际业务访问质量。阿里云服务…

跟着pink老师前端入门教程(JavaScript)-day03

四、常量 概念&#xff1a;使用 const 声明的变量称为“常量”。 使用场景&#xff1a;当某个变量永远不会改变的时候&#xff0c;就可以使用 const 来声明&#xff0c;而不是let。 命名规范&#xff1a;和变量一致 常量使用&#xff1a; 注意&#xff1a;常量不允许重新…

今日Arxiv最热大模型论文:大语言模型真的理解上下文了吗?新研究揭示惊人发现

探索大型语言模型的上下文理解能力 在自然语言处理&#xff08; Natural Language Processing,NLP&#xff09;领域&#xff0c;理解上下文是把握人类语言的关键。近年来&#xff0c;大语言模型&#xff08;LLMs&#xff09;在展示对语言的理解方面取得了令人瞩目的成就。然而…

【论文解读】Latency-Aware Collaborative Perception

Latency-Aware Collaborative Perception 摘要引言方法SystemSyncNet 实验 摘要 协作感知最近显示出提高单智能体感知感知能力的巨大潜力。现有的协同感知方法通常考虑理想的通信环境。然而&#xff0c;在实践中&#xff0c;通信系统不可避免地存在延迟问题&#xff0c;导致安…

Java_方法(重载方法签名等详解)

在之前我们学习C语言时&#xff0c;当我们想要重复使用某段代码的功能时&#xff0c;我们会将这段代码定义为一个函数&#xff0c;而在java中我们把这段重复使用的代码叫做方法。 方法的定义 类体的内容分为变量的声明和方法的定义&#xff0c;方法的定义包括两部分&#xff1…

基于协同过滤的时尚穿搭推荐系统

项目&#xff1a;基于协同过滤的时尚穿搭推荐系统 摘 要 基于协同过滤的时尚穿搭推荐系统是一种能自动从网络上收集信息的工具&#xff0c;可根据用户的需求定向采集特定数据信息的工具&#xff0c;本项目通过研究服饰流行的分析和预测的分析和预测信息可视化时尚穿搭推荐系统…

多线程---线程同步,线程通信

线程同步 1.概述 线程同步是多线程编程中的一个重要概念&#xff0c;它指的是在多线程环境中&#xff0c;通过一定的机制保证多个线程按照某种特定的方式正确、有序地执行。这主要是为了避免并发问题&#xff0c;如死锁、竞态条件、资源争用等&#xff0c;确保数据的一致性和完…

分布式文件系统 SpringBoot+FastDFS+Vue.js【一】

分布式文件系统 SpringBootFastDFSVue.js【一】 一、分布式文件系统1.1.文件系统1.2.什么是分布式文件系统1.3.分布式文件系统的出现1.3.主流的分布式文件系统1.4.分布式文件服务提供商1.4.1.阿里OSS1.4.2.七牛云存储1.4.3.百度云存储 二、fastDFS2.1.fastDSF介绍2.2.为什么要使…

【STM32】软件SPI读写W25Q64芯片

目录 W25Q64模块 W25Q64芯片简介 硬件电路 W25Q64框图 Flash操作注意事项 状态寄存器 ​编辑 指令集 INSTRUCTIONS​编辑 ​编辑 SPI读写W25Q64代码 硬件接线图 MySPI.c MySPI.h W25Q64 W25Q64.c W25Q64.h main.c 测试 SPI通信&#xff08;W25Q64芯片简介&am…

【C++学习手札】多态:掌握面向对象编程的动态绑定与继承机制(深入)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;世界上的另一个我 1:02━━━━━━️&#x1f49f;──────── 3:58 &#x1f504; ◀️ ⏸ ▶️ ☰ &am…

Python函数(一)

目录 一、定义函数 &#xff08;一&#xff09;向函数传递信息 &#xff08;二&#xff09;实参和形参 二、传递实参 &#xff08;一&#xff09;位置实参 &#xff08;二&#xff09;关键字实参 &#xff08;三&#xff09;默认值 &#xff08;四&#xff09;等效的函…

Code Composer Studio (CCS) - Comment (注释)

Code Composer Studio [CCS] - Comment [注释] References Add Block Comment: 选中几行代码 -> 鼠标右键 -> Source -> Add Block Comment shortcut key: Ctrl Shift / Remove Block Comment: 选中几行代码->鼠标右键->Source->Remove Block Comment s…

redis为什么使用跳跃表而不是树

Redis中支持五种数据类型中有序集合Sorted Set的底层数据结构使用的跳跃表&#xff0c;为何不使用其他的如平衡二叉树、b树等数据结构呢&#xff1f; 1&#xff0c;redis的设计目标、性能需求&#xff1a; redis是高性能的非关系型&#xff08;NoSQL&#xff09;内存键值数据…

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

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

蓝桥杯官网填空题(寻找整数)

问题描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 有一个不超过 10^17 的正整数 n&#xff0c;知道这个数除以 2 至 49 后的余数如下表所示&#xff0c;求这个正整数最小是多少。 运行限制 最大运行时间&#xff1a;…

Pr教程1-8节笔记

第一课 认识PR以及PR的学习方法 学习任务&#xff1a; 1、熟练掌握PR软件&#xff0c;同时掌握剪辑技术以及常用于制作特效的效果器。 2、认识PR软件的名称、主要功能以及用途作用。 3、明白学习PR我们能做些什么以及PR的学习方法。 知识内容&#xff1a; 1、PR是专门用于视…

EasyUI动态加载组件

要实现如下的效果&#xff0c;在表格中显示进度条 主要是需要再次初始化组件&#xff0c;借用ChatGPT的意思是&#xff1a; 在许多 JavaScript UI 框架中&#xff0c;包括 EasyUI&#xff0c;在动态地创建或插入新的 DOM 元素后&#xff0c;通常需要手动初始化相关的组件或特性…