资讯专栏INFORMATION COLUMN

passive的作用和原理

nanchen2251 / 3150人阅读

摘要:直接由合成线程处理的事件不经过内核线程就能快速处理的输入事件为手势输入事件滑动捏合。划重点最骚的来了,虽然手势事件可以不在内核线程处理,但是手势事件的产生还是离不开内核线程。

passived到底有什么用?

passived主要用于优化浏览器页面滚动的性能,让页面滚动更顺滑~~

passived产生的历史时间线

addEventListener():大家都是认识的,为dom添加触发事件,故事就从这里开始。
在早期addEventListener是这样的:

addEventListener(type, listener, useCapture)

useCapture:是否允许事件捕捉,但是很少会传true,然后就变成可选项了:

addEventListener(type, listener[, useCapture ])

到现在就变成了这个样子:

addEventListener(type, listener, {
    capture: false, //捕获
    passive: false, 
    once: false    //只触发一次
})

我们的主角passive就出现了

passive为什么能优化页面的滚动性能? 简述chrome的线程化渲染框架 chrome的线程化渲染框架的两个线程:

内核线程(Main/Render Thread):负责DOM树构建、元素的布局、图层绘制记录部分(main-thread side)、JavaScript的执行

合成线程(Compositor Thread):图层绘制实现部分(impl-side)、图层图像合成


上图可知,页面Frame#1在内核线程中完成js执行、布局和绘制后,经过一个周期合成线程去执行Frame#1页面图像的合成。

用户输入事件分类:

在内核线程处理的事件

直接由合成线程处理的事件

那么有什么区别呢?

在内核线程处理的事件:需要经过内核线程处理的输入事件要在内核线程执行逻辑,遇到内核线程在忙,无法立即响应。如用户的大部分输入事件都跟页面元素有关系,一旦页面元素注册了对应事件的监听器,监听器的逻辑代码(JavaScript)必须在内核线程中执行(V8引擎运行在内核线程),因此这种输入事件经常无法立即得到响应。
直接由合成线程处理的事件:不经过内核线程就能快速处理的输入事件为手势输入事件(滑动、捏合)

划重点:最骚的来了,虽然手势事件可以不在内核线程处理,但是手势事件的产生还是离不开内核线程。

页面卡顿的原因

手势事件有个属性 cancelable,作用是告诉浏览器该事件是否允许监听器通过 preventDefault() 方法阻止,默认为true。如果在touch事件内部调用preventDefault(),事件默认行为被取消,页面也就静止不动了。但是浏览器并不知道touch事件内部是否调用了preventDefault(),浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身无法优化这种场景。手势输入事件是由连续的普通输入事件组成的,在这种场景下,无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。

而Chrome团队从统计数据中分析得出,注册了mousewheel/touch相关事件监听器的页面中,80%的页面内部都不会调用preventDefault函数来阻止事件的默认行为。对于这80%的页面,即使监听器内部什么都没有做,相对没有注册mousewheel/touch事件监听器的页面,在滑动流畅度上,有10%的页面增加至少100ms的延迟,1%的页面甚至增加500ms以上的延迟。Chrome团队认为对于统计中的这80%的页面来说,他们都是不希望因为注册mousewheel/touch相关事件监听器而导致滑动延迟增加的。

passive的诞生

所以,passive 监听器诞生了,passive 的意思是“顺从的”,表示它不会对事件的默认行为说 no,浏览器知道了一个监听器是 passive 的,它就可以在两个线程里同时执行监听器中的 JavaScript 代码和浏览器的默认行为了。

经过上面的分析,我们了解到了Passive Event Listeners特性实际上是为了解决浏览器页面滑动流畅度而设计的,它通过扩展事件属性passive让Web开发者来告知浏览器监听器是否会阻止事件的默认行为,从而让浏览器可以更智能地决策并优化,这其中涉及到了Chrome的多线程渲染框架、输入事件处理等知识。

总结
参考自:
https://blog.csdn.net/dj0379/...
http://www.cnblogs.com/ziyunf...

本文主要是对上面提及两篇文章的总结和整理,理顺一下自己的思路。如果我写得不够明白可以去看看两位大佬的文章。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99721.html

相关文章

  • 阻止微信浏览器下拉滑动效果(ios11.3 橡皮筋效果)

    摘要:一前言浏览器在移动端有一个默认触摸滚动的效果,让我们感触最深的莫过于微信浏览器里面,下拉时自带橡皮筋的效果。二解释微信在端和端使用的不是同样的浏览器内核版微信浏览器浏览器内核相当于使用的版微信浏览器相当于使用的所以下面分别使用和来分析。 在升级到 ios11.3 系统后,发现之前阻止页面滚动的代码e.preventDefault代码失效了。于是自己折腾了一番,找到了解决办法,分享给大家...

    cangck_X 评论0 收藏0
  • React禁止页面滚动踩坑实践与方案梳理

    摘要:最近在使用技术栈重构一个单页应用,其中有个页面是实现城市选择功能,主要是根据城市的首字母来快速跳转到相应位置,比较类似原生中的电话联系人查找功能,页面如图主要问题在上下滑动右侧定位的元素时,页面会跟着一起滑动当然这个现象在开发过程中应该会经 最近在使用 React 技术栈重构一个单页应用,其中有个页面是实现城市选择功能,主要是根据城市的首字母来快速跳转到相应位置,比较类似原生 APP ...

    zhjx922 评论0 收藏0
  • js常见基础对象属性方法 (二)

    摘要:常见基础对象属性方法二关于的箭头函数的返回对象的问题箭头函数具有隐式返回的特性。返回值函数累计处理的结果。语句将某个对象添加的作用域链的顶部,如果在中又某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。 js常见基础对象属性方法 (二) 关于es6的箭头函数的返回对象的问题 箭头函数(=>)具有隐式返回的特性。如果某个函数体只有单个表达式,你就可以忽略r...

    Donald 评论0 收藏0
  • webapp页面滚动卡顿解决办法

    摘要:手机浏览器在滚动当前页面还可能是缩放页面时,由于默认行为被阻止,导致页面被迫静止,导致用户使用体验差,感觉滚动页面有停顿感。具体一点的解释由于事件对象的属性为,也就是说它的默认行为可以被监听器通过方法阻止。 手机浏览器在滚动当前页面(还可能是缩放页面)时,由于默认行为被阻止,导致页面被迫静止,导致用户使用体验差,感觉滚动页面有停顿感。 具体一点的解释:由于 touchstart 事件对...

    OnlyLing 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<