前端遇到页面卡顿问题的排查和解决方法
作者:程序员小寒
对于前端页面来讲,页面卡顿是一个常见的性能问题,这里主要从造成页面卡顿的原因、如何检测和排查页面卡顿、以及优化页面卡顿的最佳实践这三个方向进行分析,本文通过代码示例给大家详细的讲解一下
对于前端页面来讲,页面卡顿是一个常见的性能问题,这里主要从造成页面卡顿的原因、如何检测和排查页面卡顿、以及优化页面卡顿的最佳实践这三个方向进行分析。
一、造成页面卡顿的原因
1.1 页面掉帧
- 回流和重绘多:优化DOM操作。
- DOM节点多:采用分页、虚拟列表等方式进行优化。
1.2 内存占用高,存在内存泄漏
1.2.1 全局变量引起的内存泄漏
- js 有个特点,未声明的变量会直接挂载到
window
上,也被称为隐式全局变量,这样虽然方便后续变量访问,但会造成内存泄漏。
<script> a = 1; // 相当于 window.a = 1; </script>
- 在
window
上挂载大内存对象:
// 分配100万个32位浮点数(约4MB内存) 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); // 模拟一个耗时3秒的同步长任务
二、页面卡顿如何排查
2.1 使用 Chrome DevTools 性能分析
// 手动开始性能分析 console.profile('性能分析'); // 执行可能卡顿的代码 ... // 手动结束性能分析 console.profileEnd('性能分析');
然后就可以在 Chrome DevTools
的 Performance 面板中查看详细分析结果。
2.2 测量代码执行时间
// 使用console.time console.time('操作计时'); // 执行可能卡顿的操作 console.timeEnd('操作计时'); // 使用performance API获取更精确的时间 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
:将计算密集型任务移出主线程。
以上就是前端遇到页面卡顿问题得排查和解决方法的详细内容,更多关于前端遇到页面卡顿的资料请关注脚本之家其它相关文章!