JavaScript 第17章:性能优化

在JavaScript第17章中讨论的性能优化是一个重要的主题,因为它直接影响到Web应用的表现。下面是一些关键点以及如何进行性能优化的方法。

性能度量:性能监控工具

工具
  • 浏览器开发者工具(如Chrome DevTools)中的Performance面板可以用来记录页面加载时间和各个资源加载的时间。
  • Lighthouse 是一个开源的自动化工具,可以审计网页并提供改进建议。
  • WebPageTest 允许你在不同的浏览器和网络条件下测试网站性能。
指标
  • First Contentful Paint (FCP) - 页面上首次绘制内容的时间。
  • Largest Contentful Paint (LCP) - 大型内容元素渲染完成的时间,是衡量首屏加载的关键指标。
  • First Input Delay (FID) - 用户首次与页面交互的时间延迟。
  • Cumulative Layout Shift (CLS) - 页面布局变化的累积分数,用于评估页面稳定性。

代码优化:减少DOM操作、避免重绘与回流

技巧
  • 批量操作 - 将多个DOM操作组合在一起,使用DocumentFragment来减少重绘。
  • 使用requestAnimationFrame - 对于动画效果,使用requestAnimationFrame代替setTimeout或setInterval。
  • 事件委托 - 使用事件委托来减少事件监听器的数量。
  • 属性优化 - 避免修改style属性,而是使用CSS类来控制样式更改。

资源加载优化:懒加载、图片优化

方法
  • 懒加载 - 只有当元素进入视口时才加载图片或其他资源。
  • 使用WebP格式 - WebP是一种现代图像格式,可以在保持高质量的同时减小文件大小。
  • 图片尺寸匹配 - 确保图片尺寸与显示尺寸相匹配,避免不必要的下载和缩放。

首屏加载时间优化:预加载、关键CSS

措施
  • 预加载 - 使用<link rel="preload">来提前加载关键资源。
  • 关键CSS - 提取首屏所需CSS,将其内联在HTML文档中,避免额外的HTTP请求。

实战案例:性能优化策略的应用

示例
  • 电商网站 - 通过将首页的图片设置为懒加载,并且只加载用户当前浏览区域内的图片,可以显著提高首页的加载速度。
  • 博客平台 - 通过提取关键CSS,并将非关键部分的CSS异步加载,可以加速首屏内容的显示时间。
  • 在线视频播放器 - 利用requestAnimationFrame优化视频播放的流畅性,并通过懒加载技术加载视频中的广告或推荐内容。

性能优化是一个持续的过程,需要不断地测试、分析和调整。了解你的用户群体和他们的网络环境可以帮助你做出更明智的决策。同时,随着Web技术的发展,新的工具和技术也会不断出现,所以保持学习和实践是非常重要的。

代码优化:减少DOM操作、避免重绘与回流

减少DOM操作

当你需要频繁地更新DOM时,可以先创建一个DocumentFragment,然后将所有的DOM变动都添加到这个片段中,最后一次性将它添加到DOM树中。

javascript 复制代码
function updateDom() {
    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 1000; i++) {
        const div = document.createElement('div');
        div.textContent = `Item ${i}`;
        fragment.appendChild(div);
    }
    document.body.appendChild(fragment);
}
避免重绘与回流

尽量避免在循环中修改DOM元素的样式或结构,因为这会导致浏览器进行多次重绘和回流。

javascript 复制代码
// 不好的做法
function badPractice() {
    const div = document.getElementById('myDiv');
    for (let i = 0; i < 100; i++) {
        div.style.backgroundColor = 'red';
        div.style.backgroundColor = 'blue';
    }
}

// 好的做法
function goodPractice() {
    const div = document.getElementById('myDiv');
    div.classList.add('red');
    div.classList.remove('blue');
}

资源加载优化:懒加载、图片优化

图片懒加载

使用 Intersection Observer API 来检测图片何时进入可视区,只有当图片进入可视区时才加载它们。

html 复制代码
<img src="placeholder.png" data-src="real-image.jpg" class="lazy"/>

<script>
document.addEventListener('DOMContentLoaded', () => {
    const images = document.querySelectorAll('.lazy');
    const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                entry.target.src = entry.target.dataset.src;
                observer.unobserve(entry.target); // 停止观察已经加载的图片
            }
        });
    }, {threshold: 0.5});

    images.forEach(img => observer.observe(img));
});
</script>

首屏加载时间优化:预加载、关键CSS

关键CSS

将首屏需要的CSS内联到HTML中,避免额外的HTTP请求。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>关键CSS示例</title>
<style>
    .main {
        /* 这里放置首屏需要的关键CSS */
        background-color: #f4f4f4;
        padding: 10px;
    }
</style>
</head>
<body>
<div class="main">
    <!-- 页面内容 -->
</div>
<!-- 非关键CSS异步加载 -->
<link rel="stylesheet" href="styles.css" onload="this.rel='preload'; this.οnlοad=null;">
</body>
</html>
预加载

使用<link rel="preload">来告诉浏览器提前加载重要的资源。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Preload Example</title>
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">
</head>
<body>
<!-- 页面内容 -->
</body>
</html>

这些示例展示了如何通过不同的技术来优化JavaScript应用程序的性能。实际应用中,可能需要根据具体情况调整代码逻辑和优化策略。

当然,让我们继续探讨更多的性能优化技巧,并结合具体的源代码示例。

实战案例:性能优化策略的应用

1. 动画优化

问题:动画卡顿,尤其是在移动设备上。

解决方案 :使用requestAnimationFrame代替setTimeoutsetInterval,并且尽可能利用硬件加速。

javascript 复制代码
function animate(element, duration, targetPosition) {
    let start = null;
    function step(timestamp) {
        if (!start) start = timestamp;
        const progress = Math.min(1, (timestamp - start) / duration);
        element.style.transform = `translateX(${progress * targetPosition}px)`;
        if (progress < 1) {
            requestAnimationFrame(step);
        }
    }
    requestAnimationFrame(step);
}

const box = document.getElementById('box');
animate(box, 2000, 200);

在这个例子中,我们使用了requestAnimationFrame来确保动画帧是在屏幕刷新周期之间执行,从而获得更平滑的动画效果。

2. 事件处理优化

问题:大量的事件监听器导致性能下降。

解决方案:使用事件委托来减少事件监听器的数量。

html 复制代码
<ul id="list">
    <li data-id="1">Item 1</li>
    <li data-id="2">Item 2</li>
    <!-- 更多列表项 -->
</ul>

<script>
document.getElementById('list').addEventListener('click', event => {
    if (event.target.tagName === 'LI') {
        const id = event.target.getAttribute('data-id');
        console.log(`Clicked on item with ID: ${id}`);
    }
});
</script>

在这个例子中,我们不是给每个列表项单独添加事件监听器,而是给包含所有列表项的容器添加了一个监听器,并检查事件的目标元素是否是我们关心的类型。

3. CSS 优化

问题:过多的CSS选择器计算导致重绘和回流。

解决方案:简化选择器,尽量使用类名而不是ID或标签名。

css 复制代码
/* 不好 */
#content .list li.active {
    color: red;
}

/* 好 */
.list-item.active {
    color: red;
}

在CSS中,尽量避免使用过于复杂的嵌套选择器,并使用类名来标识状态或样式,这样可以减少浏览器计算样式规则的时间。

4. 数据处理优化

问题:大数据集处理导致页面卡顿。

解决方案:使用Web Workers来处理数据,避免阻塞主线程。

javascript 复制代码
// main.js
if (window.Worker) {
    const worker = new Worker('worker.js');
    worker.postMessage([1, 2, 3, 4, 5]); // 发送数据到Worker
    worker.onmessage = function(event) {
        console.log('Received:', event.data);
    };
} else {
    console.error('Web Workers are not supported in this browser.');
}

// worker.js
self.onmessage = function(event) {
    const result = event.data.map(x => x * 2);
    postMessage(result); // 发送结果回主线程
};

在这个例子中,我们使用Web Workers来处理复杂的数据操作,从而释放主线程进行UI渲染和其他任务。

相关推荐
Aurora_th4 分钟前
蓝桥杯py组入门(bfs广搜)
python·蓝桥杯·bfs·宽度优先
黑客学长-刘备5 分钟前
终于有人把网络安全就业方向一口气讲清了(非常详细)零基础入门到精通,收藏这一篇就够了
java·运维·服务器·网络·python·安全·web安全
小爬虫程序猿5 分钟前
Java爬虫:在1688上“照片快递”上传图片
java·开发语言·爬虫
奔跑的小蜗牛哈哈5 分钟前
使用redis实现发布订阅功能及问题
数据库·redis·bootstrap
Json_181790144806 分钟前
小红书笔记详情API接口系列(概述到示例案例)
开发语言·python
小呆i11 分钟前
Vue生成名片二维码带logo并支持下载
前端·javascript·vue.js
沃野_juededa26 分钟前
微信小程序app.js里面onLaunch里面的函数比page里面的onshow里面的方法后执行
javascript·微信小程序·小程序
热爱生活热爱你27 分钟前
Qt5 读写共享内存,已验证,支持汉字的正确写入和读取
开发语言·qt
柳鲲鹏28 分钟前
QT访问数据库:应用提示Driver not loaded
数据库
大G哥32 分钟前
MyBatis 源码分析 - SQL执行过程(三)之 ResultSetHandler
数据库·sql·microsoft·mybatis