在前端开发中,性能优化是一个永恒的话题。良好的性能不仅能提升用户体验,还能减少服务器压力,降低带宽成本。本文将介绍三种常见的前端性能优化技术:函数节流(Throttle)、函数防抖(Debounce)和图片懒加载(Lazy Load),并通过代码示例展示如何实现它们。

一、函数节流(Throttle)

1.1 、什么是节流?

节流是指在一定时间间隔内,无论事件触发多少次,函数只执行一次。就像水龙头一样,限制流量。

1.2 、应用场景

  • 滚动事件处理

  • 窗口resize事件

  • 鼠标移动事件(mousemove)

  • 频繁点击按钮

2.1、未使用节流前

<template>
  <div class="scroll-container" @scroll="throttledScroll">
    <div class="content">
      <p v-for="item in 50" :key="item">{{ item }}</p>
    </div>
  </div>
</template>

<script setup>
const throttledScroll = () =>{
  console.log('滚动了');
  
}

</script>

<style scoped>
.scroll-container {
  width: 100%;
  height: 300px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  padding: 10px;
}

.content {
  padding: 10px;
}

</style>
每次滚动都会触发throttledScroll处理函数频繁触发但不需要每次都执行的事件

3.1、方案一:使用 Lodash

npm install lodash
<template>
  <div class="scroll-container" @scroll="throttledScroll">
    <div class="content">
      <p v-for="item in 50" :key="item">{{ item }}</p>
    </div>
  </div>
</template>

<script setup>
import { throttle } from 'lodash';
// 节流后的滚动处理函数
const throttledScroll = throttle((event) => {
  console.log('滚动事件被触发', event);
}, 2000); // 2000毫秒内只执行一次
</script>

<style scoped>
.scroll-container {
  width: 100%;
  height: 300px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  padding: 10px;
}

.content {
  padding: 10px;
}

p {
  margin: 10px 0;
  font-size: 16px;
}
</style>

使用第三方库Lodash,从开始滚到两秒后滚动事件被触发

3.2、方案二:手动实现

<template>
  <div class="scroll-container" @scroll="throttledScroll">
    <div class="content">
      <p v-for="item in 50" :key="item">{{ item }}</p>
    </div>
  </div>
</template>

<script setup>
let lastExecTime = 0;
const throttledScroll = () => {
  const now = Date.now();
  if (now - lastExecTime >= 2000) { // 2秒内只执行一次
    console.log('手动节流触发');
    lastExecTime = now;
  }
};
</script>

<style scoped>
.scroll-container {
  width: 100%;
  height: 300px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  padding: 10px;
}

.content {
  padding: 10px;
}

p {
  margin: 10px 0;
  font-size: 16px;
}
</style>

节流(Throttle)在前端开发中的主要好处

节流(Throttle)是一种重要的前端性能优化技术,它在许多场景下都能显著提升应用性能和用户体验。以下是节流技术的主要好处:

4.1、 减少不必要的函数执行

核心优势:节流确保函数在一定时间间隔内只执行一次,避免了短时间内多次重复执行。

  • 例如在滚动事件中,不加节流可能导致每秒触发几十次事件处理函数

  • 使用节流后可以控制在每秒只执行2-3次,大大减少计算量

4.2、 提升页面性能和流畅度

性能提升:通过限制高频事件的触发频率,减轻浏览器负担。

  • 防止因过多事件处理导致的页面卡顿

  • 减少不必要的DOM操作和重绘/回流

  • 特别在低端移动设备上效果更为明显

4.3、优化资源使用

资源节省:减少CPU、内存和网络资源消耗。

  • 避免短时间内发送大量网络请求(如滚动加载更多内容)

  • 减少复杂计算的执行频率

  • 降低内存占用,防止内存泄漏风险

4.4.、平衡性能和响应性

智能平衡:在保持良好用户体验的同时优化性能。

  • 不像防抖那样完全延迟到最后才执行

  • 保证用户能感受到一定的即时反馈

  • 在性能和响应速度之间取得良好平衡

4.5.、适用场景广泛

应用灵活:适用于多种高频事件场景。

  • 窗口resize事件处理

  • 滚动事件(scroll)监听

  • 鼠标移动(mousemove)跟踪

  • 游戏中的按键处理

  • 无限滚动加载更多内容

  • 拖拽操作的位置计算

4.6.、实现简单但效果显著

开发效率:简单的实现带来明显的性能提升。

  • 通常只需几行代码即可实现

  • 可以封装为通用工具函数重复使用

  • 容易与其他优化技术(如防抖)结合使用

二、函数防抖(Debounce)

2.1 、什么是防抖?

防抖是指事件触发后,等待一段时间再执行函数。如果在这段时间内事件再次触发,则重新计时。类似于电梯关门,如果有人进来就重新计时。

2.2、 应用场景

  • 搜索框输入联想

  • 表单验证

  • 窗口resize事件(停止改变后再执行)

  • 防止重复提交

2.3、 实现代码

方案一:使用 Lodash

使用前

<template>
  <input @input="debouncedSearch" placeholder="请输入搜索内容" />
</template>

<script setup>
const debouncedSearch = () =>{
  console.log('我输入了内容'); 
}
</script>

每次在搜索框输入内容就会触发debouncedSearch函数

使用防抖后

<template>
  <input @input="debouncedSearch" placeholder="搜索" />
</template>

<script setup>
import { debounce } from 'lodash';

const debouncedSearch = debounce(() => {
  console.log('防抖'); // 500ms后执行
}, 500);
</script>

当不输入内容500ms后触发函数

方案二:手动实现

<template>
  <input @input="debouncedSearch" placeholder="手动防抖" />
</template>

<script setup>

let timeoutId = null;
const debouncedSearch = () => {
  clearTimeout(timeoutId);
  timeoutId = setTimeout(() => {
    console.log('手动防抖'); // 500ms后执行
  }, 500);
};
</script>

防抖(Debounce)在前端开发中的核心优势

防抖(Debounce)是一种重要的函数调优技术,特别适合处理高频触发的事件。以下是防抖技术的主要好处及其应用价值:

1、 减少不必要的计算和请求

核心价值:确保函数只在事件停止触发后执行一次,避免中间过程的多余计算。

  • 搜索框输入联想:只在用户停止输入后才发送请求

  • 表单验证:避免每次按键都进行验证

  • 自动保存功能:在用户停止编辑后才执行保存

2、优化网络请求频率

请求控制:有效防止短时间内发送大量重复请求。

  • 避免搜索建议接口被频繁调用

  • 减少API服务器的压力

  • 节省移动设备的网络流量

  • 防止重复提交表单数据

3、提升复杂操作的性能

性能保护:对资源密集型操作提供缓冲期。

  • 复杂的DOM操作(如动态渲染大量元素)

  • 大数据量的计算处理

  • 高频的动画状态计算

4、防止重复提交

数据安全:特别适用于表单提交场景。

  • 避免用户多次点击提交按钮导致重复提交

  • 保护后端接口不被意外多次调用

  • 减少数据库重复写入风险

5、资源占用优化

效率提升:显著降低浏览器资源消耗。

  • 减少内存占用(避免累积未完成的函数调用)

  • 降低CPU使用率(避免连续执行复杂计算)

  • 优化事件处理队列(减少待处理事件数量)

三、图片懒加载(Lazy Load)

3.1 、什么是图片懒加载?

懒加载是一种延迟加载技术,只有当图片进入或即将进入可视区域时才加载图片,而不是页面加载时就加载所有图片。

3.2 、为什么需要懒加载?

  • 减少页面加载时间

  • 节省带宽

  • 提升用户体验

  • 减轻服务器压力

3.3、代码实现

方案一:使用 Intersection Observer API 原生实现
<script setup>
import { ref, onMounted } from 'vue';

const lazyImages = ref([]);

onMounted(() => {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        observer.unobserve(img);
      }
    });
  }, {
    rootMargin: '0px 0px 100px 0px' // 提前100px加载
  });

  lazyImages.value.forEach(img => {
    observer.observe(img);
  });
});
</script>

<template>
  <div class="image-container">
    <img 
      v-for="(image, index) in 10" 
      :key="index"
      ref="lazyImages"
      :data-src="`https://picsum.photos/800/400?random=${index}`"
      alt="Lazy loaded image"
      class="lazy-image"
    >
  </div>
</template>

<style>
.lazy-image {
  width: 100%;
  height: 400px;
  object-fit: cover;
  margin-bottom: 20px;
  background: #eee;
  display: block;
}
</style>
方案二:使用 vue-lazyload 插件
npm install vue-lazyload

安装完成以后在main.js中全局注册

import { createApp } from 'vue';
import App from './App.vue';
import VueLazyload from 'vue-lazyload';

const app = createApp(App);

app.use(VueLazyload, {
  preLoad: 1.3,
  error: 'https://via.placeholder.com/800x400?text=Error',
  loading: 'https://via.placeholder.com/800x400?text=Loading',
  attempt: 1
});

app.mount('#app');

在页面中使用v-lazy指令

<template>
  <div class="image-container">
    <img 
      v-for="(image, index) in 10" 
      :key="index"
      v-lazy="`https://picsum.photos/800/400?random=${index}`"
      alt="Lazy loaded image"
      class="lazy-image"
    >
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const lazyImages = ref([]);

onMounted(() => {
  // 如果需要额外的 IntersectionObserver 逻辑,可以保留
  // 但通常 vue-lazyload 已经处理了这些逻辑
});
</script>

<style>
.lazy-image {
  width: 100%;
  height: 400px;
  object-fit: cover;
  margin-bottom: 20px;
  background: #eee;
  display: block;
}
</style>

四、性能对比与总结

4.1、 优化前后对比

指标优化前优化后
页面加载时间
内存占用
滚动流畅度可能卡顿流畅
网络请求一次性大量请求按需请求

4.2、 总结

  1. 节流(Throttle):控制函数执行频率,适用于频繁触发但不需要每次都执行的事件

  2. 防抖(Debounce):确保函数只在事件停止触发后执行一次,适用于输入联想等场景

  3. 图片懒加载:延迟加载非可视区域的图片,显著提升页面加载速度

在实际项目中,我们可以根据具体需求选择合适的优化策略,甚至可以组合使用这些技术。现代浏览器提供的API(如IntersectionObserver)让这些优化实现起来更加简单高效。

希望本教程能帮助你理解并应用这些前端性能优化技术,为你的项目带来更好的用户体验!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐