前端事件流(js原生事件流)

来源网友投稿 773 2022-12-26

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。
本篇文章给大家谈谈前端事件流,以及js原生事件流对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。 今天给各位分享前端事件流的知识,其中也会对js原生事件流进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

前端面试题,js事件机制是什么?

事件流前端事件流:指从页面中接收事件前端事件流的顺序前端事件流,有冒泡流和捕获流。
当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体顺序是怎样前端事件流的呢?冒泡和捕获则描述了两种不同的顺序。

关于前端的几个知识点,劳烦知友帮忙解答一下

1、DOM结构——两个节点之间可能存在哪些关系以及如何在节点之间任意移动。
document.documentElement 返回文档的根节点<html
document.body <body
document.activeElement 返回当前文档中被击活的标签节点(ie)
event.fromElement 返回鼠标移出的源节点(ie)
event.toElement 返回鼠标移入的源节点(ie)
event.srcElement 返回激活事件的源节点(ie)
event.target 返回激活事件的源节点(firefox)
当前对象为node
返回父节点:node.parentNode, node.parendElement,
返回所有子节点:node.childNodes(包含文本节点及标签节点),node.children
返回第一个子节点:node.firstChild
返回最后一个子节点: node.lastChild
返回同属上一个子节点:node.nextSibling
返回同属下一个子节点:node.previousSibling
parentNode和parentElement功能一样,childNodes和children功能一样。但是parentNode和
childNodes是符合W3C标准的,可以说比较通用。而另外两个只是IE支持,不是标准,Firefox就不支持
,所以大家只要记得有parentElement和children就行了
2、DOM操作——怎样添加、移除、移动、复制、创建和查找节点。
(1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore()
(3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
3、事件——怎样使用事件以及IE和DOM事件模型之间存在哪些主要差别。
(1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
IE 5.5: div - body - document
IE 6.0: div - body - html - document
Mozilla 1.0: div - body - html - document - window
(2)捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
(3)DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。
DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。
4、XMLHttpRequest——这是什么、怎样完整地执行一次GET请求、怎样检测错误。
XMLHttpRequest 对象提供了在网页加载后与服务器进行通信的方法。
<script type="text/javascript"
varxmlhttp;
functionloadXMLDoc(url){
xmlhttp=null;
if(window.XMLHttpRequest){ //code for all new browsers
xmlhttp=newXMLHttpRequest();
}elseif(window.ActiveXObject){ //code for IE5 and IE6
xmlhttp=newActiveXObject("Microsoft.XMLHTTP");
}
if(xmlhttp!=null){
xmlhttp.onreadystatechange=state_Change;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}else{
alert("Your browser does not support XMLHTTP.");
}
}
functionstate_Change(){
if(xmlhttp.readyState==4){ //4 = "loaded"
if(xmlhttp.status==200){ //200 = OK
//...our code here...
}else{
alert("Problem retrieving XML data");
}
}
}
</script
5、严格模式与混杂模式——如何触发这两种模式,区分它们有何意义。
在标准模式中,浏览器根据规范呈现页面;
在混杂模式中,页面以一种比较宽松的向后兼容的方式显示。
浏览器根据DOCTYPE是否存在以及使用的哪种DTD来选择要使用的呈现方法。如果XHTML文档包含形式完整的DOCTYPE,那么它一般以标准模式
呈现。对于HTML
4.01文档,包含严格DTD的DOCTYPE常常导致页面以标准模式呈现。包含过渡DTD和URI的DOCTYPE也导致页面以标准模式呈现,但是有过
渡DTD而没有URI会导致页面以混杂模式呈现。DOCTYPE不存在或形式不正确会导致HTML和XHTML文档以混杂模式呈现。
6、盒模型——外边距、内边距和边框之间的关系,IE 8以下版本的浏览器中的盒模型有什么不同。
一个元素盒模型的层次从内到外分别为:内边距、边框和外边距
IE8以下浏览器的盒模型中定义的元素的宽高不包括内边距和边框
7、块级元素与行内元素——怎么用CSS控制它们、它们怎样影响周围的元素以及你觉得应该如何定义它们的样式。
块级元素,用CSS中的display:inline;属性则变为行内元素
行内元素,用CSS中的display:block;属性则变为块级元素
影响:周围元素显示在同一行或换行显示,根据具体情况调整样式
8、浮动元素——怎么使用它们、它们有什么问题以及怎么解决这些问题。
需要浮动的元素可使用CSS中float属性来定义元素的浮动位置,left:往左浮动,right:往右浮动
浮动元素引起的问题:
(1)父元素的高度无法被撑开,影响与父元素同级的元素
(2)与浮动元素同级的非浮动元素会跟随其后
(3)若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构
解决方法:
使用CSS中的clear:both;属性来清除元素的浮动可解决2、3问题,对于问题1,添加如下样式,给父元素添加clearfix样式:
.clearfix:after{content: ".";display: block;height: 0;clear: both;visibility: hidden;}
.clearfix{display: inline-block;} /* for IE/Mac */
9、HTML与XHTML——二者有什么区别,你觉得应该使用哪一个并说出理由。
主要区别:
XHTML 元素必须被正确地嵌套
XHTML 元素必须被关闭,空标签也必须被关闭,如 <br 必须写成 <br /
XHTML 标签名必须用小写字母
XHTML 文档必须拥有根元素
XHTML 文档要求给所有属性赋一个值
XHTML 要求所有的属性必须用引号""括起来
XHTML 文档需要把所有 < 、、 等特殊符号用编码表示
XHTML 文档不要在注释内容中使“--”
XHTML 图片必须有说明文字
XHTML 文档中用id属性代替name属性
10、JSON——它是什么、为什么应该使用它、到底该怎么使用它,说出实现细节来。
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。
JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value
pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表
(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

前端经典面试题(包含JS、CSS、React、浏览器等)

防抖

节流

误区前端事件流:我们经常说get请求参数前端事件流的大小存在限制前端事件流,而post请求的参数大小是无限制的。

实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制前端事件流了url的长度。为了明确这个概念,我们必须再次强调下面几点:

补充补充一个get和post在缓存方面的区别:

可从IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、

vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。在交叉对比中,当新节点跟旧节点 头尾交叉对比 没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key = index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。vue部分源码如下:

创建map函数

遍历寻找

在React中, 如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。

**原因:**在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是, 有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state 。

虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能。

具体实现步骤如下:

用 JavaScript 对象结构表示 DOM 树的结构前端事件流;然后用这个树构建一个真正的 DOM 树,插到文档当中

当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异

把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了。

结构:display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击

继承:display: none:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。

性能:displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大 visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容 opacity: 0 :修改元素会造成重绘,性能消耗较少

联系:它们都能让元素不可见

常用的一般为三种 .clearfix , clear:both , overflow:hidden ;

比较好是 .clearfix ,伪元素万金油版本,后两者有局限性.

clear:both :若是用在同一个容器内相邻元素上,那是贼好的,有时候在容器外就有些问题了, 比如相邻容器的包裹层元素塌陷

overflow:hidden :这种若是用在同个容器内,可以形成 BFC 避免浮动造成的元素塌陷

概念:将多个小图片拼接到一个图片中。通过 background-position 和元素尺寸调节需要显示的背景图案。

优点:

缺点:

block 元素特点:

1.处于常规流中时,如果 width 没有设置,会自动填充满父容器 2.可以应用 margin/padding 3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略 vertical-align

inline 元素特点

1.水平方向上根据 direction 依次布局

2.不会在元素前后进行换行

3.受 white-space 控制

4. margin/padding 在竖直方向上无效,水平方向上有效

5. width/height 属性对非替换行内元素无效,宽度由元素内容决定

6.非替换行内元素的行框高由 line-height 确定,替换行内元素的行框高由 height , margin , padding , border 决定 7.浮动或绝对定位时会转换为 block 8. vertical-align 属性生效

GIF :

JPEG :

PNG :

七种数据类型

(ES6之前)其中5种为基本类型: string , number , boolean , null , undefined ,

ES6出来的 Symbol 也是原始数据类型 ,表示独一无二的值

Object 为引用类型(范围挺大),也包括数组、函数,

输出结果是:

工厂模式

简单的工厂模式可以理解为解决多个相似的问题;

单例模式

只能被实例化(构造函数给实例添加属性与方法)一次

沙箱模式

将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值

发布者订阅模式

就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,

代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组

1.字面量

2.Object构造函数创建

3.使用工厂模式创建对象

4.使用构造函数创建对象

HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。

什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段。

addEventListener : addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

IE只支持事件冒泡 。

获取一个对象的原型,在chrome中可以通过__proto__的形式,或者在ES6中可以通过Object.getPrototypeOf的形式。

那么Function.proto是什么么?也就是说Function由什么对象继承而来,我们来做如下判别。

我们发现Function的原型也是Function。

我们用图可以来明确这个关系:

这里来举个栗子,以 Object 为例,我们常用的 Object 便是一个构造函数,因此我们可以通过它构建实例。

则此时, 实例为instance , 构造函数为Object ,我们知道,构造函数拥有一个 prototype 的属性指向原型,因此原型为:

这里我们可以来看出三者的关系:

在 JS 中,继承通常指的便是 原型链继承 ,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。

在函数式编程中,函数是一等公民。那么函数柯里化是怎样的呢?

函数柯里化指的是将能够接收多个参数的函数转化为接收单一参数的函数,并且返回接收余下参数且返回结果的新函数的技术。

函数柯里化的主要作用和特点就是参数复用、提前返回和延迟执行。

在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数 ,供多次重复调用。

call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。

除了第一个参数外, call 可以接收一个参数列表, apply 只接受一个参数数组。

bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。

如何实现一个 bind 函数

对于实现以下几个函数,可以从几个方面思考

如何实现一个call函数

如何实现一个apply函数

箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this 。在这个例子中,因为调用 a 符合前面代码中的第一个情况,所以 this 是 window 。并且 this 一旦绑定了上下文,就不会被任何代码改变。

在函数中,我们首先使用 var 关键字声明了 name 变量。这意味着变量在创建阶段会被提升( JavaScript 会在创建变量创建阶段为其分配内存空间),默认值为 undefined ,直到我们实际执行到使用该变量的行。我们还没有为 name 变量赋值,所以它仍然保持 undefined 的值。

使用 let 关键字(和 const )声明的变量也会存在变量提升,但与 var 不同,初始化没有被提升。在我们声明(初始化)它们之前,它们是不可访问的。这被称为“暂时死区”。当我们在声明变量之前尝试访问变量时, JavaScript 会抛出一个 ReferenceError 。

关于 let 的是否存在变量提升,我们何以用下面的例子来验证:

let 变量如果不存在变量提升, console.log(name) 就会输出 ConardLi ,结果却抛出了 ReferenceError ,那么这很好的说明了, let 也存在变量提升,但是它存在一个“暂时死区”,在变量未初始化或赋值前不允许访问。

变量的赋值可以分为三个阶段:

关于 let 、 var 和 function :

依次输出:undefined - 10 - 20

答案: D

colorChange 方法是静态的。静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。由于 freddie 是一个子级对象,函数不会传递,所以在 freddie 实例上不存在 freddie 方法:抛出 TypeError 。

1.使用第一次push,obj对象的push方法设置 obj[2]=1;obj.length+=1 2.使用第二次push,obj对象的push方法设置 obj[3]=2;obj.length+=1 3.使用console.log输出的时候,因为obj具有 length 属性和 splice 方法,故将其作为数组进行打印 4.打印时因为数组未设置下标为 0 1 处的值,故打印为empty,主动 obj[0] 获取为 undefined

undefined {n:2}

首先,a和b同时引用了{n:2}对象,接着执行到a.x = a = {n:2}语句,尽管赋值是从右到左的没错,但是.的优先级比=要高,所以这里首先执行a.x,相当于为a(或者b)所指向的{n:1}对象新增了一个属性x,即此时对象将变为{n:1;x:undefined}。之后按正常情况,从右到左进行赋值,此时执行a ={n:2}的时候,a的引用改变,指向了新对象{n:2},而b依然指向的是旧对象。之后执行a.x = {n:2}的时候,并不会重新解析一遍a,而是沿用最初解析a.x时候的a,也即旧对象,故此时旧对象的x的值为{n:2},旧对象为 {n:1;x:{n:2}},它被b引用着。后面输出a.x的时候,又要解析a了,此时的a是指向新对象的a,而这个新对象是没有x属性的,故访问时输出undefined;而访问b.x的时候,将输出旧对象的x的值,即{n:2}。

在比较相等性,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。 JavaScript 检查对象是否具有对内存中相同位置的引用。

我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。

这就是为什么 { age: 18 } === { age: 18 } 和 { age: 18 } == { age: 18 } 返回 false 的原因。

所有对象键(不包括 Symbols )都会被存储为字符串,即使你没有给定字符串类型的键。这就是为什么 obj.hasOwnProperty('1') 也返回 true 。

上面的说法不适用于 Set 。在我们的 Set 中没有 “1” : set.has('1') 返回 false 。它有数字类型 1 , set.has(1) 返回 true 。

这题考察的是对象的键名的转换。

catch 块接收参数 x 。当我们传递参数时,这与变量的 x 不同。这个变量 x 是属于 catch 作用域的。

之后,我们将这个块级作用域的变量设置为 1 ,并设置变量 y 的值。现在,我们打印块级作用域的变量 x ,它等于 1 。

在 catch 块之外, x 仍然是 undefined ,而 y 是 2 。当我们想在 catch 块之外的 console.log(x) 时,它返回 undefined ,而 y 返回 2 。

web前端开发学javascript中的哪些内容?

DOM:DOM操作 DOM1 DOM2 DOM3 。
事件:事件流 冒泡 捕获
作用域,数据类型-obj array(js中没有真正的array类型,console一个arr出来的是obj)date string number 布尔 ,json,xhr(ajax) 等等
框架、库:jq CMD sea.js 等等(视需求而定,jq算是必备技能吧。) angular.js倒觉得了解就可以了。
多学点nodejs也挺好的,现在许多公司都在用node做中间层,也是一些公司前端必备的技能。
另外,js就是为web生的,看书的话都看看吧,像《js高级程序设计》、犀牛书这些,买一本当作工具书,有什么不会的地方翻一番。还有ff的开发者论坛,东西比较全。
欢迎补充。

怎样深入了解和学习前端 MVC 架构

好处和具体操作如下:
可以由不同的人并行推进对model和view的内部实现,而不关心对方怎么实现,只管负责自己内部的实现并抛出事件,并约定好通过事件所传递的数据的格式即可,就像前端和后端的分离那样。
从容应对灵活多变的业务需求,只要在controler中修改所绑定的事件名和实现相应操作的回调函数即可。controler要做的就是做决定:决定在哪个事件被抛出时,调用实现哪个操作的方法。这就是它为什么叫做controler的原因。而它只做决定,不做实现,体现了 “We need thin controler"(http://c2.com/cgi/wiki?ModelViewController) 的原则。
可以很方便的卸载、装载以及修改各个特性。装载:在model/view中提供实现该特性的方法,在controler中把该方法的调用和调用时机(即事件)绑定起来即可。卸载:解除事件绑定即可。修改:参考好处2。
坏处就是有点麻烦,需要controler这一层绑定事件。
分离总是会导致引入一种中间层的,就像以前把DOM事件回调直接写在html元素的onclick事件当中,后来为了结构和行为分离,需要在js中获取该html元素,然后再addEventListener,才能把事件和事件回调函数关联起来。
至于需不需要这个灵活度,看具体的场景而定了。需要这种灵活度的场景还是存在的,而且不少。毕竟,计算机领域的大部分问题都可以通过加入某种中间层来解决。

聊一聊浏览器事件循环与前端性能

在网上也看了不少关于javascript事件循环的文章前端事件流,多数是以浏览器事件循环与nodejs中事件循环做对比,分析两种环境的差异。下面说的内容是浏览器事件循环与前端性能之间的关系,了解之后在开发中规避一些性能问题。以下所探讨的事件循环皆指浏览器的事件循环,本文属于个人理解,如有不对欢迎提点。

  提到事件循环,相信现在多数前端小白并不陌生了。首先事件循环分为宏任务和微任务。
宏任务前端事件流:鼠标事件,键盘事件,网络事件,Html解析, 定时器等前端事件流
微任务前端事件流:Dom变化,Promise;

  当这些事件发生的时候浏览器会在对应的事件队列(宏任务队列和微任务队列)中添加该事件处理器(回调函数)等待执行。而事件循环是一直循环着看事件队列中是否还有未处理的处理器,如果有的话就从队列首位取出处理器执行,执行完之后就移除对应处理器,就是这样一直循环着直到浏览器关闭为止,即使事件队列为空!但是在处理宏任务队列和微任务队列的方式不同。

在一次事件循环中只能处理一个宏任务,而需要处理所有微任务直到微任务队列清空
说明:事件循环是在主程序执行完之后就开始循环执行事件,主程序说简单点就是一个js文件从第一行执行到最后一行,主程序结束(此处说的是该应用就一个js文件)
举一个生活中的例子:
  银行中排队办理业务的时候,假设每个排队等待办理的普通客户是宏任务,而VIP客户是微任务。那么在银行早上开始上班的之前,柜员启动相应的机器(电脑,打印机等)属于主程序,等一切准备好之后就开始办理业务了。假如现在有10个普通用户(宏任务)在等待,开始处理第一个客户,处理完之后叫号第二个客户,开始处理。如果在处理第二个客户的时候突然来个一个vip用户,那么在处理为完普通用户之后就轮到处理VIP用户(微任务),如果在处理VIP用户的时候又来了个VIP用户的话3号普通客户就得等待处理完两个VIP客户。当然此处举例皆是只该银行就一个服务窗口,复合js单线程模式。

下图是一个完整的事件循环图:

  浏览器通常会尝试60秒渲染一次页面,以达到每秒60帧(60fps)的速度, 60fps是检验前端体验是否流畅的标准,在动画里就意味着当浏览器没16ms一次刷新的话,体验是最流畅的,所有在整个页面生命周期中每一次事件循环都应该在16ms内完成。
但是在事件循环中可能会处理比较耗时的任务,那么渲染就会延后这样就会导致动画看上去不流畅,更严重的可能是页面处于假死状态等影响用户体验。
如果加上UI渲染的话上面的事件循环图是这样的

  上面提到浏览器会尝试16ms重新渲染页面,那么假如在处理事件的时候遇到耗时任务的时候,浏览器将会延迟渲染页面,如果处理不当那将会导致体验差问题。接下来仔细分析以下整个流程。
  首先先排除为任务,只有宏任务的程序。现在有两个点击事件

假如主线程运行需要15ms,btn1事件处理器完成需要8ms, btn2需要10ms;那么整个流程是这样:

假如用户点击速度很快的时候,主线程运行期间在5ms和12ms时候分别点击了btn1,btn2按钮,触发点击事件,此时因为还处与主线程运行时间内,所有此时会向宏任务队列添加两个事件任务。当主线程运行到15ms时结束,此时浏览器可以重新渲染。渲染完之后进入事件循环,首先从任务队列中取出任务btn1事件处理器执行,此过程会耗时8ms,处理完之后结束一次事件循环,并移除事件处理器btn1。此时浏览器可以重新渲染,渲染完之后又进行到第二次事件循环,重复上述步骤,直到事件队列清空为止。
  如果事件循环中存在为任务的话流程如下:

其实只是在宏任务之后加入了一个时间段处理为任务.。在第一循环中处理btn1事件处理器时添加promise1到微任务队列中,在执行完btn1事件之后检查微任务队列发现有一个任务待处理,然后取出处理之后移除微任务promise1在循环微任务队列,发现以微任务队列为空,28ms时浏览器可以重新渲染(此时浏览器距离上次渲染相差12ms,渲染流畅)。在执行第二次事件循环的时候,在执行到微任务队列时,需要处理两个任务,耗时8ms,46ms时浏览器可以重新渲染(此时浏览器距离上次渲染相差18ms,渲染流畅)。
总结:如果在事件循环中有的任务比较耗时,会导致浏览器渲染fps变小,从而导致用户体验差。如向页面中插入10000个td节点的时候,如果是一次循环就appendChild一次,那相当于总共会有10000个微任务待执行,这样就会影响到浏览器渲染的fps,所有会出现点击页面没有反响的体验,这就是为什么插入多个节点需要拼接到一起一次性插入节点。了解事件循环和浏览器渲染之间到联系之后,以后开发多注意一些耗时任务到处理,到此分享结束。

关于前端事件流和js原生事件流的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。 前端事件流的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于js原生事件流、前端事件流的信息别忘了在本站进行查找喔。
上一篇:四维智联与途虎联手推动汽车后市场产品服务全面转型升级
下一篇:重载货车智能运维平台哪个好(小货车货运平台哪个好)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~