awesome-interview/book1/browser-repain-reflow/index.html

17 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.5">
<title data-react-helmet="true">浏览器的重排重绘 | HZFE - 剑指前端 Offer</title><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:url" content="https://hzfe.github.io/awesome-interview/book1/browser-repain-reflow"><meta data-react-helmet="true" name="docusaurus_locale" content="en"><meta data-react-helmet="true" name="docusaurus_version" content="current"><meta data-react-helmet="true" name="docusaurus_tag" content="docs-default-current"><meta data-react-helmet="true" property="og:title" content="浏览器的重排重绘 | HZFE - 剑指前端 Offer"><meta data-react-helmet="true" name="description" content="相关问题"><meta data-react-helmet="true" property="og:description" content="相关问题"><link data-react-helmet="true" rel="shortcut icon" href="/awesome-interview/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://hzfe.github.io/awesome-interview/book1/browser-repain-reflow"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book1/browser-repain-reflow" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book1/browser-repain-reflow" hreflang="x-default"><link rel="stylesheet" href="/awesome-interview/assets/css/styles.36d1aa8c.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.21038279.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.de89bd10.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div><a href="#" class="skipToContent_1oUP">Skip to main content</a></div><nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><b class="navbar__title">剑指前端 Offer</b></a></div><div class="navbar__items navbar__items--right"><a href="https://github.com/hzfe/awesome-interview" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_3J9K"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_31aa"><button class="clean-btn backToTopButton_35hR" type="button"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_3Kbt"><div class="sidebar_15mo"><nav class="menu thin-scrollbar menu_Bmed menuWithAnnouncementBar_2WvA"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/awesome-interview/">前言</a></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">模拟题一</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/browser-cross-origin">浏览器:浏览器跨域</a></li><li class="menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/awesome-interview/book1/browser-repain-reflow">浏览器:浏览器的重排重绘</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/engineer-webpack-workflow">工程化Webpack 工作流程</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/frame-vue-data-binding">框架Vue 的数据绑定机制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/frame-vue-computed-watch">框架Vue 的 computed 和 watch 的区别</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/js-closures">基础:闭包的作用和原理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/js-module-specs">基础:前端模块化规范</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/css-bfc">样式BFC 的形成和作用</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/network-security">网络:前端安全</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/coding-promise">编码:实现一个 Promises/A+</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/algorithm-balanced-binary-trees">算法:平衡二叉树</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book1/topic-enter-url-display-xx">综合:浏览器从输入网址到页面展现的过程</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题二</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题三</a></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_1CGd"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_3E-R"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_3ufF"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_3FnS"><div class="docItemContainer_33ec"><article><div class="tocCollapsible_1PrD tocMobile_3Hoh"><button type="button" class="clean-btn tocCollapsibleButton_2O1e">On this page</button></div><div class="markdown"><header><h1>浏览器的重排重绘</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_31ik" id="相关问题"></a>相关问题<a class="hash-link" href="#相关问题" title="Direct link to heading">#</a></h2><ul><li>如何提升页面渲染性能</li><li>如何减少页面重排重绘</li><li>哪些行为会引起重排/重绘</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_31ik" id="回答关键点"></a>回答关键点<a class="hash-link" href="#回答关键点" title="Direct link to heading">#</a></h2><p><code>渲染性能</code> <code>Layout</code> <code>Paint</code></p><p>浏览器渲染大致分为四个阶段,其中在解析 HTML 后,会依次进入 Layout 和 Paint 阶段。<strong>样式或节点的更改,以及对布局信息的访问等</strong>,都有可能导致重排和重绘。而重排和重绘的过程在<strong>主线程</strong>中进行,这意味着不合理的重排重绘会导致<strong>渲染卡顿,用户交互滞后</strong>等性能问题。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_31ik" id="知识点深入"></a>知识点深入<a class="hash-link" href="#知识点深入" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithStickyNavbar_31ik" id="1-什么是重排重绘"></a>1. 什么是重排重绘<a class="hash-link" href="#1-什么是重排重绘" title="Direct link to heading">#</a></h3><p><img src="https://user-images.githubusercontent.com/17002181/126033732-d5002255-1c88-4dee-9371-da166aacdca9.png" alt="image"></p><p><strong>Layout布局</strong></p><blockquote><p>指浏览器计算各元素的几何信息,确定元素的大小以及在页面中的位置等信息的过程。</p></blockquote><p><strong>Paint绘制/栅格化)</strong></p><blockquote><p>指将渲染树中的每个节点转换成屏幕上的实际像素的过程。</p></blockquote><p>浏览器从获取文档、样式、脚本等内容,到最终渲染结果到屏幕上,需要经过如图所示的步骤。而 DOM 或 CSSOM 被修改,会导致浏览器重复执行图中的步骤。重排和重绘,本质上指的就是分别重新触发 Layout 和 Paint 的过程,且重排必定导致重绘。</p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithStickyNavbar_31ik" id="引起重排重绘的常见操作"></a>引起重排/重绘的常见操作<a class="hash-link" href="#引起重排重绘的常见操作" title="Direct link to heading">#</a></h4><ol><li>外观有变化时,会导致<strong>重绘</strong>。相关的样式属性如 <code>color</code> <code>opacity</code> 等。</li><li>布局结构或节点内容变化时,会导致<strong>重排</strong>。相关的样式属性如 <code>height</code> <code>float</code> <code>position</code> 等。<ul><li>盒子尺寸和类型。</li><li>定位方案(正常流、浮动和绝对定位)。</li><li>文档树中元素之间的关系。</li><li>外部信息(如视口大小等)。</li></ul></li><li>获取布局信息时,会导致<strong>重排</strong>。相关的方法属性如 <code>offsetTop</code> <code>getComputedStyle</code> 等。</li></ol><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithStickyNavbar_31ik" id="2-如何减少重排重绘"></a>2. 如何减少重排重绘<a class="hash-link" href="#2-如何减少重排重绘" title="Direct link to heading">#</a></h3><p><img src="https://user-images.githubusercontent.com/17002181/126033739-3e689aab-fcd8-4928-9e6d-6a047ab2a8c9.png" alt="image"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithStickyNavbar_31ik" id="意义"></a>意义<a class="hash-link" href="#意义" title="Direct link to heading">#</a></h4><p>大多数显示器的刷新率是 60FPSframes per second。理想情况下浏览器需要在 1/60 秒内完成渲染阶段并交付一帧。这样用户就会看到一个交互流畅的页面。</p><p>在交互阶段,页面更新(一般是通过执行 JavaScript 来触发)通常会触发重排和重绘。为了提升浏览器渲染效率,应当尽可能减少重绘重排,降低浏览器渲染耗费的时间,尽快将内容渲染到屏幕上。</p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithStickyNavbar_31ik" id="解决方案"></a>解决方案<a class="hash-link" href="#解决方案" title="Direct link to heading">#</a></h4><ol><li>对 DOM 进行批量写入和读取(通过虚拟 DOM 或者 DocumentFragment 实现)。</li><li>避免对样式频繁操作,了解常用样式属性触发 Layout / Paint / Composite 的<a href="https://csstriggers.com/" target="_blank" rel="noopener noreferrer">机制</a>,合理使用样式。</li><li>合理利用特殊样式属性(如 transform: translateZ(0) 或者 will-change将渲染层提升为合成层开启 GPU 加速,提高页面性能。</li><li>按需缓存布局信息,避免频繁读取。</li></ol><p>另外,可以借助 DevTools Performance 面板来查看产生重排重绘任务占用主线程的情况和调用代码。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithStickyNavbar_31ik" id="参考资料"></a>参考资料<a class="hash-link" href="#参考资料" title="Direct link to heading">#</a></h2><ol><li><a href="https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=zh-cn" target="_blank" rel="noopener noreferrer">渲染树构建、布局及绘制</a></li><li><a href="https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing" target="_blank" rel="noopener noreferrer">避免大型、复杂的布局和布局抖动</a></li><li><a href="https://csstriggers.com/" target="_blank" rel="noopener noreferrer">CSS 属性触发布局、绘制及合成的数据</a></li><li><a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a" target="_blank" rel="noopener noreferrer">What forces layout / reflow</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/awesome-interview/book1/browser-cross-origin"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 浏览器:浏览器跨域</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/awesome-interview/book1/engineer-webpack-workflow"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">工程化Webpack 工作流程 »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_35-E thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#相关问题" class="table-of-contents__link">相关问题</a></li><li><a href="#回答关键点" class="table-of-contents__link">回答关键点</a></li><li><a href="#知识点深入" class="table-of-contents__link">知识点深入</a><ul><li><a href="#1-什么是重排重绘" class="table-of-contents__link">1. 什么是重排重绘</a></li><li><a href="#2-如何减少重排重绘" class="table-of-contents__link">2. 如何减少重排重绘</a></li></ul></li><li><a href="#参考资料" class="table-of-contents__link">参考资料</a></li></ul></div></div></div><div class="row"><div class="col"><div class="react-utterences"><div>Loading script...</div></div></div><div class="col col--3"></div></div></div></main></div></div></div>
<script src="/awesome-interview/assets/js/runtime~main.21038279.js"></script>
<script src="/awesome-interview/assets/js/main.de89bd10.js"></script>
</body>
</html>