这段时间 JavaScript 原生开发做的一些优化点
最近在开发一个用原生 JavaScript 开发的项目,说实话,我平时开发的都是使用 Vue/React
进行开发,所以这次使用 JavaScript 原生开发,就需要自己去做一些性能的优化
文档碎片 DocumentFragment
当我们想要批量往页面上新增 DOM 节点的时候,如果循环遍历 appendChild 的话会比较耗性能,所以这个时候可以使用 DocumentFragment
,这样的话可以一次性批量新增 DOM 节点
const fragment = document.createDocumentFragment();
const data = ["Item 1", "Item 2", "Item 3"];
data.forEach(item => {
const element = document.createElement("div");
element.textContent = item;
fragment.appendChild(element);
});
doument.body.appendChild(fragment);
防抖节流
防抖节流属于是老生常谈了,我们很多的监听事件都需要做防抖节流,这样能减少监听事件触发的次数,从而减少性能的损耗
防抖
防抖是指在连续的事件触发后,只有最后一次事件触发之后的延迟时间到达时才执行回调函数。如果在延迟时间内再次触发事件,则之前的回调会被取消
function debounce(func, delay) {
let timeout;
return function() {
// 清除上一次的定时器
clearTimeout(timeout);
// 设置新的定时器,只有在delay时间后才执行 func
timeout = setTimeout(() => {
func.apply(this, arguments);
}, delay);
}
}
// 示例调用
const searchInput = document.getElementById('searchInput');
// 在用户停止输入后500ms才触发回调
searchInput.addEventListener('input', debounce(function() {
console.log("用户输入:", this.value);
}, 500))
节流
节流是指在一定的时间间隔内,只允许函数执行一次,哪怕该时间间隔内事件触发了很多次
function throttle(func, interval) {
let lastTime = 0;
return function() {
let nowTime = new Date().getTime();
if (nowTime - lastTime >= interval) {
func.apply(this, arguments);
lastTime = nowTime;
}
}
}
// 示例使用
// 每一秒执行一次
const scrollEvent = throttle(function() {
console.log("滚动事件触发");
}, 1000)
window.addEventListener("scroll", scrollEvent)
Web Worker
Web Worker
是一种在后台线程中运行 JavaScript 的技术,能够使网页在执行长时间运行的任务时不阻塞主线程,避免页面卡顿。通过 Web Worker,我们可以将一些繁重的计算任务交给独立的线程来处理,从而提高网页的性能和用户体验
// worker.js - Web Worker 代码
self.onmessage = function(e) {
console.log("Worker 收到消息:", e.data);
// 进行一些计算,比如模拟耗时任务
let result = e.data * 2; // 假设是简单的计算任务
self.postMessage(result); // 将计算结果发送给主线程
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Web Worker Example</title>
</head>
<body>
<h1>Web Worker 示例</h1>
<button id="startBtn">开始计算</button>
<p id="result">计算结果:</p>
<script>
// 创建一个新的 Web Worker
const worker = new Worker('worker.js');
// 监听从 Web Worker 返回的消息
worker.onmessage = function(e) {
document.getElementById('result').textContent = "计算结果:" + e.data;
};
// 错误处理
worker.onerror = function(e) {
console.error("Worker 错误:", error.message);
};
// 触发事件,向Web Worker 发送数据
document.getElementById('startBtn').addEventListener('click', function() {
const number = 10;
console.log("发送数据到Worker:", number);
worker.postMessage(number); // 向 Web Worker 发送数据
});
</script>
</body>
</html>
浏览器缓存
需要后台给前端返回缓存的响应头,这样读取文件的时候就能读取缓存
// 设置缓存时间为一年
Cache-control: public, max-age=31536000
异步加载 JavaScript 脚本
当你页面需要加载的 JavaScript 脚本过多的时候,可以选择异步加载 JavaScript 脚本,这涉及到了 script 标签的 defer/async
特性 | defer | async |
加载方式 | 异步加载,但等待HTML解析完成后执行 | 异步加载,加载完成后立即执行 |
执行顺序 | 按照在文档中的顺序执行 | 执行顺序不确定,取决于哪个脚本先加载完成 |
适用场景 | 适用于需要访问DOM的脚本 | 适用于不依赖DOM的独立脚本 |
是否阻塞Html | 不阻塞,HTML继续解析 | 不阻塞,HTML继续解析 |
<script src="script1.js" defer></script>
<script src="script2.js" async></script>