對于前端頁面來講,頁面卡頓是一個常見的性能問題,這里主要從造成頁面卡頓的原因、如何檢測和排查頁面卡頓、以及優化頁面卡頓的最佳實踐這三個方向進行分析。
一、造成頁面卡頓的原因
1.1 頁面掉幀
- 回流和重繪多:優化DOM操作。
- DOM節點多:采用分頁、虛擬列表等方式進行優化。
1.2 內存占用高,存在內存泄漏
1.2.1 全局變量引起的內存泄漏
- js 有個特點,未聲明的變量會直接掛載到
window
上,也被稱為隱式全局變量,這樣雖然方便后續變量訪問,但會造成內存泄漏。
<script>
a = 1;
</script>
- 在
window
上掛載大內存對象:
window.largeFloatArray = new Float32Array(1000000);
1.2.2 閉包引起的內存泄漏
function addEvent(){
const el = document.getElementById("button");
const hugeData = new Array(100000).join("hello");
el.addEventListener("click", ()=>{
console.log(hugeData)
})
}
addEvent();
這里通過閉包引用了 hugeData
,導致 hugeData
無法被回收,從而造成內存泄漏。需要在合適的時機移除掉事件監聽器。
1.2.3 定時器引起的內存泄露
function genTimer(){
let count = 0;
setInterval(function(){
count++;
console.log(count);
})
}
genTimer();
這里的 setInterval
定時器的回調函數引用了外部的 count
變量,如果在合適的時機沒有清除定時器,就會導致內存泄漏。
1.2.4 未解除的DOM引用造成的內存泄漏
let el = document.getElementById('button');
如果 el
被存儲在某個地方,并且該元素被移除,但 el
仍然被引用,那么它將不會被垃圾回收,從而導致內存泄漏。
1.2.5 循環引用
循環引用指的是兩個或多個對象相互引用,形成一個循環結構,導致無法被回收。
let a = {};
let b = {};
a.c = b;
b.c = a;
1.3 長任務
由長任務會讓 JavaScript
執行時間過長,導致渲染不及時,頁面卡頓。
function longSyncTask(duration) {
const start = performance.now();
while (performance.now() - start < duration) {
}
console.log(`同步長任務完成,耗時 ${performance.now() - start}ms`);
}
longSyncTask(3000);
二、頁面卡頓如何排查
2.1 使用 Chrome DevTools 性能分析
console.profile('性能分析');
console.profileEnd('性能分析');
然后就可以在 Chrome DevTools
的 Performance 面板中查看詳細分析結果。
2.2 測量代碼執行時間
console.time('操作計時');
console.timeEnd('操作計時');
const start = performance.now();
const duration = performance.now() - start;
console.log(`操作耗時: ${duration}毫秒`);
2.3 長任務檢測
使用 PerformanceObserver API
可以檢測檢測長任務(>50ms)。
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('長任務:', entry);
}
});
observer.observe({ entryTypes: ['longtask'] });
2.4 幀率(FPS)監控
let lastTime = performance.now();
let frameCount = 0;
function checkFPS() {
const now = performance.now();
frameCount++;
if (now > lastTime + 1000) {
const fps = Math.round((frameCount * 1000) / (now - lastTime));
console.log(`當前FPS: ${fps}`);
if (fps < 30) {
console.warn('幀率過低,可能存在性能問題');
}
frameCount = 0;
lastTime = now;
}
requestAnimationFrame(checkFPS);
}
requestAnimationFrame(checkFPS);
前端頁面的 FPS(Frames Per Second 每秒幀數,代表頁面的流暢度和卡頓程度)如果低于 30 幀,就可以認為頁面出現明顯卡頓的情況。 一般來說,FPS 在 60 幀及以上能夠提供流暢的用戶體驗,但如果頁面中包含大量的動畫、視頻、音頻,導致元素數量、復雜度、計算量等過高,那就需要更高的 FPS 才能讓頁面很流暢。
三、優化頁面卡頓的最佳實踐
- 分批處理大任務:使用
requestIdleCallback
或 setTimeout
分塊執行。 - 避免頻繁DOM操作:使用文檔片段或虛擬DOM。
- 優化動畫:使用
requestAnimationFrame
而非 setTimeout
。 - 使用
Web Worker
:將計算密集型任務移出主線程。
?轉自https://juejin.cn/post/7534922574057930798
該文章在 2025/8/7 17:18:17 編輯過