筆記

css will-change

will-change屬性可以提前通知瀏覽器我們要對(duì)元素做什么動(dòng)畫(huà),這樣瀏覽器可以提前準(zhǔn)備合適的優(yōu)化設(shè)置。這樣可以避免對(duì)頁(yè)面響應(yīng)速度有重要影響的昂貴成本。元素可以更快的被改變,渲染的也更快,這樣頁(yè)面可以快速更新,表現(xiàn)的更加流暢。

舉個(gè)例子,當(dāng)對(duì)于素使用 CSS 3D變形時(shí),元素及其內(nèi)容可以在合成到頁(yè)面之前被創(chuàng)建到我們之前說(shuō)的layer。然而把元素放到layer中是個(gè)昂貴的操作,這將會(huì)導(dǎo)致變形動(dòng)畫(huà)延遲一個(gè)課件的瞬間,也就是flicker

為了避免這種延時(shí),我們可以在發(fā)生之前通知瀏覽器,這樣瀏覽器會(huì)有一定的時(shí)間去準(zhǔn)備這些變化,當(dāng)發(fā)生的時(shí)候layer已經(jīng)準(zhǔn)備好了,這樣動(dòng)畫(huà)酒會(huì)很流暢,不會(huì)閃屏

使用will-change提示瀏覽器關(guān)于即將發(fā)生的變形十分簡(jiǎn)單,添加個(gè)CSS屬性就行

will-change: transform;
也可以告訴瀏覽器要改變?cè)氐臐L動(dòng)條位置,或者多個(gè)要變化的屬性,寫(xiě)下屬性的名字就行,也可以寫(xiě)多個(gè),逗號(hào)隔開(kāi)

will-change: transform, opacity;
聲明了元素即將進(jìn)行的變化會(huì)讓瀏覽器在渲染頁(yè)面時(shí)做更好的決定,這明顯比之前說(shuō)的3D hacks要好。

參考鏈接

Load 和 DOMContentLoaded 區(qū)別

Load 事件觸發(fā)代表頁(yè)面中的 DOM,CSS,JS,圖片已經(jīng)全部加載完畢。

DOMContentLoaded 事件觸發(fā)代表初始的 HTML 被完全加載和解析,不需要等待 CSS,JS,圖片加載。

Node 中的 Event loop

防抖

節(jié)流

重繪(Repaint)和回流(Reflow)

重繪和回流是渲染步驟中的一小節(jié),但是這兩個(gè)步驟對(duì)于性能影響很大。

  • 重繪是當(dāng)節(jié)點(diǎn)需要更改外觀而不會(huì)影響布局的,比如改變 color 就叫稱(chēng)為重繪
  • 回流是布局或者幾何屬性需要改變就稱(chēng)為回流。

回流必定會(huì)發(fā)生重繪,重繪不一定會(huì)引發(fā)回流?;亓魉璧某杀颈戎乩L高的多,改變深層次的節(jié)點(diǎn)很可能導(dǎo)致父節(jié)點(diǎn)的一系列回流。

所以以下幾個(gè)動(dòng)作可能會(huì)導(dǎo)致性能問(wèn)題:

  • 改變 window 大小
  • 改變字體
  • 添加或刪除樣式
  • 文字改變
  • 定位或者浮動(dòng)
  • 盒模型

很多人不知道的是,重繪和回流其實(shí)和 Event loop 有關(guān)。

  1. 當(dāng) Event loop 執(zhí)行完 Microtasks 后,會(huì)判斷 document 是否需要更新。因?yàn)闉g覽器是 60Hz 的刷新率,每 16ms 才會(huì)更新一次。
  2. 然后判斷是否有 resize 或者 scroll ,有的話會(huì)去觸發(fā)事件,所以 resizescroll 事件也是至少 16ms 才會(huì)觸發(fā)一次,并且自帶節(jié)流功能。
  3. 判斷是否觸發(fā)了 media query
  4. 更新動(dòng)畫(huà)并且發(fā)送事件
  5. 判斷是否有全屏操作事件
  6. 執(zhí)行 requestAnimationFrame 回調(diào)
  7. 執(zhí)行 IntersectionObserver 回調(diào),該方法用于判斷元素是否可見(jiàn),可以用于懶加載上,但是兼容性不好
  8. 更新界面
  9. 以上就是一幀中可能會(huì)做的事情。如果在一幀中有空閑時(shí)間,就會(huì)去執(zhí)行 requestIdleCallback 回調(diào)。

以上內(nèi)容來(lái)自于 HTML 文檔

減少重繪和回流

使用 translate 替代 top

<div class="test"></div>
<style>
    .test {
        position: absolute;
        top: 10px;
        width: 100px;
        height: 100px;
        background: red;
    }
</style>
<script>
    setTimeout(() => {
        // 引起回流
        document.querySelector('.test').style.top = '100px'
    }, 1000)
</script>

使用 visibility 替換 display: none ,因?yàn)榍罢咧粫?huì)引起重繪,后者會(huì)引發(fā)回流(改變了布局)

把 DOM 離線后修改,比如:先把 DOM 給 display:none (有一次 Reflow),然后你修改100次,然后再把它顯示出來(lái)

不要把 DOM 結(jié)點(diǎn)的屬性值放在一個(gè)循環(huán)里當(dāng)成循環(huán)里的變量

for(let i = 0; i < 1000; i++) {
    // 獲取 offsetTop 會(huì)導(dǎo)致回流,因?yàn)樾枰カ@取正確的值
    console.log(document.querySelector('.test').style.offsetTop)
}

不要使用 table 布局,可能很小的一個(gè)小改動(dòng)會(huì)造成整個(gè) table 的重新布局

動(dòng)畫(huà)實(shí)現(xiàn)的速度的選擇,動(dòng)畫(huà)速度越快,回流次數(shù)越多,也可以選擇使用 requestAnimationFrame

CSS 選擇符從右往左匹配查找,避免 DOM 深度過(guò)深

將頻繁運(yùn)行的動(dòng)畫(huà)變?yōu)閳D層,圖層能夠阻止該節(jié)點(diǎn)回流影響別的元素。比如對(duì)于 video 標(biāo)簽,瀏覽器會(huì)自動(dòng)將該節(jié)點(diǎn)變?yōu)閳D層。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容