[译]深入了解现代web浏览器(四)
本文是根据Mariko Kosaka在谷歌开发者网站上的系列文章https://developer.chrome.com/blog/inside-browser-part4/翻译而来,共有四篇,该篇是第四篇。对于其中一些直译出来不太好理解的句子,笔者做了加工处理和提炼。
输入来到了合成器
在上篇文章中,我们了解了渲染过程和合成器;在这片文章中,我们将来了解下合成器是如何在用户输入到来时保持交互流畅的。
从浏览器的角度看输入事件
当你听到“输入事件”时,你可能只会想到在文本框中输入或是鼠标点击;但从浏览器的角度来看,来自用户的任何动作都是输入。鼠标滚轮滚动、触摸或者鼠标悬浮都是一个输入事件。
当用户在屏幕做出触摸等动作时,浏览器进程最先接收到该动作。但是浏览器进程只关注该动作发生的位置,因为tab页中的内容是由渲染进程处理的。浏览器进程把事件类型(比如touchstart)和其坐标发送给渲染进程;渲染进程会找到对应的事件目标并执行目标上绑定的事件监听器。

通过浏览器进程路由到渲染进程的输入事件
合成器接收输入事件
在上一篇文章中,我们知道了合成器是如何通过合成光栅化的图层来达到流畅地处理滚动的。如果页面上没有绑定事件监听,合成线程可以完全独立于主线程来创建合成帧。但如果页面上绑定有事件监听呢?毕竟事件监听的回调函数只能由主线程来执行。
理解非快速滚动区域
由于运行Javascript是主线程的工作,当页面被合成时,合成线程会将页面上绑定有事件监听的区域标记为“非快速滚动区域(Non-Fast Scrollable Region)”。拥有这些信息,合成线程能够确保当有事件发生在该区域时能将输入事件发送给主线程。如果输入事件是来自该区域之外的,则合成线程会继续合成新的帧而无需等待主线程执行事件处理函数。

非快速滚动区域的输入事件
注意你编写的事件处理函数
在web开发中一种很常见的处理模式是事件委派。由于事件冒泡机制的存在,你可以在最顶层的元素绑定事件处理函数然后根据事件目标来委派处理函数。你可能见过或者写过如下的代码:
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
由于你只需要为所有的元素只编写一个处理函数,从工程学上讲这种事件委派模式很有吸引力。但如果从浏览器的角度来看这段代码,现在整个页面都被标记为了“非快速滚动区域”。这意味着,即使你的应用并不关心页面上某些部分产生的输入事件,但只要发生了输入事件,合成线程还是不得不与主线程发生通信并等待。因此,合成线程的流畅性就会收到影响。

覆盖到了整个页面的非快速滚动区域
为了减轻这种情况的影响,你可以向事件处理函数中传入passive: true选项。这能提示浏览器你在事件处理函数中不会调用event.preventDefault(),就意味着你代码中不会通过event.preventDefault()语句阻止事件的默认行为(没有这个选项的话,则需要主线程执行完你的处理函数然后才能决定是否要阻止诸如滚动、失焦之类的事件默认行为,再告知合成线程要合成新的帧)。因此,在有passive: true的情况下,就可以让主线程在执行处理函数的同时,合成线程能继续合成下一帧。
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
寻找事件目标
当主线程收到合成线程发送的输入事件后,首先要做的就是执行命中测试来找到事件目标。命中测试利用渲染阶段生成的绘制记录来找出发生事件的点坐标下方的内容。

主线程根据绘制记录查询x.y点处绘制的内容
最小化事件调度到主线程
在上一篇文章中,我们讨论了典型的显示器是如何一秒钟刷新60次并保持动画流畅的节奏。对于输入,典型的触屏设备每秒会传递60-120次触屏事件,而典型的鼠标每秒会传递100次事件。输入事件的保真度高于我们屏幕刷新频率的保真度。
如果像touchmove这样的连续事件被每秒120次地发送到主线程,那么与屏幕的刷新速度相比,它会触发过多的命中测试和Javascript执行。

帧的时间轴上被大量事件淹没导致页面卡顿
为了尽量减少在主线程上的调用,Chrome会合并连续的事件(例如wheel, mousewheel, mousemove, pointermove, touchmove)并延迟调度直至下一次requestAnimationFrame之前。

与上一张图片相同的时间轴,但事件被合并和延迟了
任何的离散事件例如keydown,keyup,mouseup,mousedown,touchstart和touchend都会被立即调度。
使用getCoalescedEvents获取帧内事件
对于绝大部分的web应用,合并事件足以提供良好的用户体验。然而,如果你正在构建诸如绘画或者基于touchmove坐标的路径放置的应用,你可能会因丢失中间坐标而不能绘画出平滑的线段。这种情况下,你可以使用指针事件中的getCoalescedEvents方法来获取更多关于这些合并事件的信息。

左侧是平滑触摸手势的路径,右侧是受合并事件限制的路径
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
})
下一步
在本系列中,我们介绍了Web浏览器的内部工作原理。如果您从未想过为什么DevTools建议在事件处理程序中添加{passive: true},或者为什么你可能要在脚本标签中写入async属性;我希望本系列文章能够阐明为什么浏览器需要这些信息来提供更快、更流畅的Web体验。
使用Lighthouse
如果你想让自己的代码对浏览器更友好但不知道从哪里开始,Lighthouse会是一个不错的工具。它可以对任何网站执行审计并提供一份报告,告知你哪些地方做的不错而哪些地方还需要改进。通过阅读审计列表,可以让你知道浏览器关心哪些指标。
了解如何衡量性能
对于不同站点性能调整会有所不同,因此如何衡量你的站点性能并确定最适合的方案是非常重要的。Chrome的DevTools团队有一些关于衡量站点性能的教程。
总结
当我开始构建网站的时候,几乎只关心书写代码和哪些能帮助我提高效率的东西。这些事当然很重要,但我们也应该思考下浏览器是如何处理我们书写的代码的。现代浏览器为给用户提供更好的web体验而持续努力。书写对浏览器“友好”的代码,这反过来会改进你的用户体验。希望你能加入我们一起追求对浏览器更为友好的世界!
[译]深入了解现代web浏览器(四)的更多相关文章
- [译]36 Days of Web Testing(四)
Day 19: UX 用户体验 Why ? 最近UX变得越来越火,用户提现往往会直接联想到易用性和设计. 在我看来,UX不仅仅是这两点.UX, User Experience ,对我而言,不单单是产 ...
- [C# 网络编程系列]专题四:自定义Web浏览器
转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...
- 转:【专题四】自定义Web浏览器
前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...
- 专题四:自定义Web浏览器
前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...
- 前端Web浏览器基于Flash如何实时播放监控视频画面(四)之使用videoJs‘拉流’
本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 0x001: 下载videoJs 对于Video.js 5.x及更低版本,Flash技术(v ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- java web 学习四(http协议)
一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...
- JavaScript权威指南--WEB浏览器中的javascript
知识要点 1.客户端javascript window对象是所有客户端javascript特性和API的主要接入点.它表示web浏览器的一个窗口或窗体,并且可以用window表示来引用它.window ...
- 前端Web浏览器基于Flash如何实时播放监控视频画面(前言)之流程介绍
[关键字:前端浏览器如何播放RTSP流画面.前端浏览器如何播放RTMP流画面] 本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 考虑到视频延 ...
- Kendo UI for jQuery使用教程:支持Web浏览器
[Kendo UI for jQuery最新试用版下载] Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support ...
随机推荐
- 云图说丨Astro Canvas一站式数据可视化开发,分钟级构建业务大屏
摘要:Astro大屏应用是Astro轻应用提供的可视化页面构建服务,提供了丰富的可视化组件.灵活的数据接入和多种方式页面构建能力,支持多屏适配,帮助开发者快速构建和发布专业水准的实时可视化应用. 本文 ...
- 华为云FusionInsight MRS在金融行业存算分离的实践
摘要:华为云FusionInsight MRS的大数据存算分离解决方案,实现资源价值最大化,存储与计算资源全面云化.灵活配置.弹性伸缩,降本增效. 在大数据.云计算.5G.AI等技术日新月异,数字经济 ...
- 想快速重构智慧园区5A系统,这份方案推荐给你
摘要:近年来,园区的数字化一直在演进,从OA.CA.BA.SA.FA等单一系统的信息化建设,到以应用为主导的大系统集成,再到以云.大数据为基础的数据开放平台构建,继而进入全量数据融合.数字技术泛在的智 ...
- CWE 4.7中的新视图:工业控制系统的安全漏洞类别
摘要:CWE今年的第一个版本在5/1前发布了,做为软件安全的重要分类标准,我们来看下这个版本有那些变化. 本文分享自华为云社区<CWE 4.7中的新视图 -- 工业控制系统的安全漏洞类别> ...
- 火山引擎 DataTester 首推 A/B 实验经验库,帮助企业高效优化实验设计能力
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,火山引擎 DataTester 推出了重要功能--A/B 实验经验库. 基于在字节跳动已完成 150 万 ...
- 白话文解析LiteFlow的理念是什么?什么时候用该怎么用?干货满满
官网:https://liteflow.cc/ Gitee:https://gitee.com/dromara/liteFlow Github:https://github.com/dromara/l ...
- The Cluster ID Zc7nlyfTQ5qPbhY2d8I_3A doesn't match stored clusterId Some(ZvQZIX9gTB-dj05be_i_-w) in meta.properties.
启动kafka时报错(部分信息): [2022-05-12 20:26:05,589] INFO Cluster ID = Zc7nlyfTQ5qPbhY2d8I_3A (kafka.server.K ...
- vmware中 centos 突然不能联网,ens33丢失,见了鬼了..........
本人笔记本上vmware中centos允许一直很稳定,今天启动centos准备docker打包,结果发现不能联网了!!! ifconfig一下,发现ens33没了,见鬼了吧! 于是一通vmware虚拟 ...
- 【数据库】E-R图向关系模型转换的规则
E-R图向关系模型转换的规则: (1) 一个实体型转换为一个关系模式,实体的属性就是关系的属性,实体的码(关键字)就是关系的码. (2) 一个 1:1 联系可以转换为一个独立的关系模式,也可以与任意一 ...
- Codeforce 515C. Drazil and Factorial(字符串思维题)
[CodeForces]C. Drazil and Factorial 题目链接:Click Here 题意:找一个最大的数,使得每个位的阶乘的乘积与给定数相同. 首先將 2~9 轉成這樣(0,1為空 ...