欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript前端優(yōu)化策略深入詳解

 更新時間:2023年05月11日 14:58:55   作者:世界和平  
在前端開發(fā)中,優(yōu)化頁面性能是非常重要的一個方面,頁面性能優(yōu)化可以提升網(wǎng)站的用戶體驗,加速頁面的加載速度,提高用戶的滿意度,本文講解了前端通用的優(yōu)化策略,需要詳細了解可以參考下

虛擬滾動

當我們開發(fā)的時候,遇到大數(shù)據(jù)加載,頁面卡頓的問題應該如何處理?大多數(shù)情況下,我們都是盡量通過分頁的方式處理這類問題,但是總有一些特殊的情況我們必須把數(shù)據(jù)全部加載到前端進行處理。我曾經(jīng)遇到過一個坑爹的組件,必須一次性加載幾萬條數(shù)據(jù)到頁面上,導致一打開這個組件,就會讓頁面瘋狂卡頓,當時便用了虛擬滾動解決了這個棘手的問題。

所以當我們遇到這種情況:渲染長列表的場景,當渲染條數(shù)過多時,所需要的渲染時間會很長,滾動時還會造成頁面卡頓,整體體驗非常不好。完全可以考慮使用虛擬滾動這個解決方案。

虛擬滾動——指的是只渲染可視區(qū)域的列表項,非可見區(qū)域的不渲染,在滾動時動態(tài)更新可視區(qū)域,該方案在優(yōu)化大量數(shù)據(jù)渲染時效果是很明顯的。以下這個圖較為清晰地解釋了虛擬滾動的工作原理。

虛擬滾動基本原理:

計算出 totalHeight 列表總高度,并在觸發(fā)時滾動事件時根據(jù) scrollTop 值不斷更新 startIndex 以及 endIndex ,以此從列表數(shù)據(jù) listData 中截取對應元素。

虛擬滾動插件

虛擬滾動的使用場景不少,網(wǎng)上有很多已經(jīng)造好的輪子,我們也可以適當?shù)剡x擇更快更便捷的方式解決我們的頁面問題。

虛擬滾動的插件有很多,比如 vue-virtual-scroller、vue-virtual-scroll-list、react-tiny-virtual-list、react-virtualized 等

這里簡單介紹 vue-virtual-scroller 的使用

// 安裝插件
npm install vue-virtual-scroller
// main.js
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
Vue.use(VueVirtualScroller)
// 使用
<template> 
  <RecycleScroller 
    class="scroller" 
    :items="list" 
    :item-size="32" 
    key-field="id" 
    v-slot="{ item }"> 
      <div class="user"> {{ item.name }} </div>
  </RecycleScroller> 
</template>

該插件主要有 RecycleScroller.vue、DynamicScroller.vue 這兩個組件,其中 RecycleScroller 需要 item 的高度為靜態(tài)的,也就是列表每個 item 的高度都是一致的,而 DynamicScroller 可以兼容 item 的高度為動態(tài)的情況

Web Worker優(yōu)化長任務

瀏覽器對頁面的渲染時單線程的,導致我們的頁面無法同時渲染CSS和JS代碼。所以由于瀏覽器 GUI 渲染線程與 JS 引擎線程是互斥的關系,當頁面中有很多長任務時,會造成頁面 UI 阻塞,出現(xiàn)界面卡頓、掉幀等情況。

如果直接把下面這段代碼直接丟到主線程中,計算過程中頁面一直處于卡死狀態(tài),無法操作。

let sum = 0;
for (let i = 0; i < 200000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random()
    }
  }

使用 Web Worker 執(zhí)行上述代碼時,計算過程中頁面正常可操作、無卡頓

// worker.js
onmessage = function (e) {
  // onmessage獲取傳入的初始值
  let sum = e.data;
  for (let i = 0; i < 200000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random()
    }
  }
  // 將計算的結果傳遞出去
  postMessage(sum);
}

Web Worker的通信時長

當然Web Worker我們也不能濫用,畢竟加載worker也是需要消耗一定的服務器資源。并不是執(zhí)行時間超過 50ms 的任務,就可以使用 Web Worker,還要先考慮通信時長的問題假如一個運算執(zhí)行時長為 100ms,但是通信時長為 300ms, 用了 Web Worker可能會更慢

比如新建一個 web worker, 瀏覽器會加載對應的 worker.js 資源,下圖中的 Time 是這個資源的通信時長(也叫加載時長)。

當任務的運算時長 - 通信時長 > 50ms,推薦使用Web Worker

requestAnimationFrame 制作動畫

頁面如果想要更加吸人眼球,動畫必不可少。但是動畫有時候會讓頁面看起來卡頓,而且也比較消耗瀏覽器的資源。那么為了解決這樣的一些問題,我們可以使用requestAnimationFrame這個API來處理我們的動畫效果。

requestAnimationFrame 是瀏覽器專門為動畫提供的 API,它的刷新頻率與顯示器的頻率保持一致,使用該 api 可以解決用 setTimeout/setInterval 制作動畫卡頓的情況。

①引擎層面

setTimeout/setInterval 屬于 JS引擎,requestAnimationFrame 屬于 GUI引擎JS引擎與GUI引擎是互斥的,也就是說 GUI 引擎在渲染時會阻塞 JS 引擎的計算。

②時間是否準確

requestAnimationFrame 刷新頻率是固定且準確的,但 setTimeout/setInterval 是宏任務,根據(jù)事件輪詢機制,其他任務會阻塞或延遲js任務的執(zhí)行,會出現(xiàn)定時器不準的情況。

③性能層面

當頁面被隱藏或最小化時,setTimeout/setInterval 定時器仍會在后臺執(zhí)行動畫任務,而使用 requestAnimationFrame 當頁面處于未激活的狀態(tài)下,屏幕刷新任務會被系統(tǒng)暫停。

JS的加載方式

關于我們頁面的加載,相信很多人都知道在單線程的加載方式下,很多時候錯誤的編碼會導致頁面的阻塞,從而影響用戶的體驗,那么關于這點,我們應該更詳細地去了解JS的加載方式。

①正常模式

<script src="index.js"></script>

這種情況下 JS 會阻塞 dom 渲染,瀏覽器必須等待 index.js 加載和執(zhí)行完成后才能去做其它事情。也就是說如果整個頁面跑下來,遇到這行代碼將會直接停止頁面dom的渲染,等到js文件加載完畢后,才能夠再去繪制頁面。

②async 模式

<script async src="index.js"></script>

async 模式下,它的加載是異步的,JS 不會阻塞 DOM 的渲染,async 加載是無順序的,當它加載結束,JS 會立即執(zhí)行。

使用場景:若該 JS 資源與 DOM 元素沒有依賴關系,也不會產(chǎn)生其他資源所需要的數(shù)據(jù)時,可以使用async 模式,比如埋點統(tǒng)計。

③defer 模式

<script defer src="index.js"></script>

defer 模式下,JS 的加載也是異步的,defer 資源會在 DOMContentLoaded 執(zhí)行之前,并且 defer 是有順序的加載。

如果有多個設置了 defer 的 script 標簽存在,則會按照引入的前后順序執(zhí)行,即便是后面的 script 資源先返回。所以 defer 可以用來控制 JS 文件的執(zhí)行順序,比如 element-ui.js 和 vue.js,因為 element-ui.js 依賴于 vue,所以必須先引入 vue.js,再引入 element-ui.js。

defer 使用場景:一般情況下都可以使用 defer,特別是需要控制資源加載順序時

④module 模式

<script type="module">import {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> a } from './a.js'</script>

在主流的現(xiàn)代瀏覽器中,script 標簽的屬性可以加上 type=“module”,瀏覽器會對其內(nèi)部的 import 引用發(fā)起 HTTP 請求,獲取模塊內(nèi)容。這時 script 的行為會像是 defer 一樣,在后臺下載,并且等待 DOM 解析。

Vite 就是利用瀏覽器支持原生的 es module 模塊,開發(fā)時跳過打包的過程,提升編譯效率。

⑤preload 模式

<link rel="preload" as="script" href="index.js" rel="external nofollow"  rel="external nofollow" >

link 標簽的 preload 屬性:用于提前加載一些需要的依賴,這些資源會優(yōu)先加載。

1)preload 加載的資源是在瀏覽器渲染機制之前進行處理的,并且不會阻塞 onload 事件;

2)preload 加載的 JS 腳本其加載和執(zhí)行的過程是分離的,即 preload 會預加載相應的腳本代碼,待到需要時自行調(diào)用;

⑥prefetch 模式

<link rel="prefetch" as="script" href="index.js" rel="external nofollow"  rel="external nofollow" >

prefetch 是利用瀏覽器的空閑時間,加載頁面將來可能用到的資源的一種機制;通??梢杂糜诩虞d其他頁面(非首頁)所需要的資源,以便加快后續(xù)頁面的打開速度。

prefetch 特點:

1)pretch 加載的資源可以獲取非當前頁面所需要的資源,并且將其放入緩存至少5分鐘(無論資源是否可以緩存)

2)當頁面跳轉時,未完成的 prefetch 請求不會被中斷

加載方式的總結

async、defer 是 script 標簽的專屬屬性,對于網(wǎng)頁中的其他資源,可以通過 link 的 preload、prefetch 屬性來預加載。

如今現(xiàn)代框架已經(jīng)將 preload、prefetch 添加到打包流程中了,通過靈活的配置,去使用這些預加載功能,同時我們也可以審時度勢地向 script 標簽添加 async、defer 屬性去處理資源,這樣可以顯著提升性能。 所以通常情況下,當我們使用了打包工具時,也不需要我們?nèi)ス芾硖鄰碗s的加載形式,只需要通過簡單的配置即可達到我們想要的效果。

到此這篇關于JavaScript前端優(yōu)化策略深入詳解的文章就介紹到這了,更多相關JS前端優(yōu)化策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論