深入理解节流(Throttle):原理、实现与应用场景

发布于:2025-09-13 ⋅ 阅读:(21) ⋅ 点赞:(0)

在前端开发中,我们经常遇到一些需要优化性能的场景,比如滚动事件、鼠标移动事件、窗口大小调整等。这些场景中,事件可能会被频繁触发,导致性能问题。节流(Throttle)是一种常见的优化技术,用于限制这些事件的触发频率,从而提高应用的性能和用户体验。


一、什么是节流?

节流的定义是:在单位时间内,最多只执行一次事件的处理函数。换句话说,节流可以确保在指定的时间间隔内,事件的处理函数最多只被触发一次。

1.1 使用场景

节流在以下场景中非常有用:

  1. 滚动事件:当用户滚动页面时,scroll 事件会频繁触发。如果没有节流,每次触发事件都会执行相应的处理函数,这会导致性能问题。使用节流后,只有在指定的时间间隔内,才会执行一次处理函数。
  2. 鼠标移动事件:当用户在某个元素上移动鼠标时,mousemove 事件会频繁触发。如果没有节流,每次触发事件都会执行相应的处理函数,这会导致性能问题。使用节流后,只有在指定的时间间隔内,才会执行一次处理函数。
  3. 窗口大小调整:当用户调整窗口大小时,resize 事件会频繁触发。如果没有节流,每次触发事件都会重新计算布局,这会导致性能问题。使用节流后,只有在指定的时间间隔内,才会重新计算一次布局。

二、节流的实现

节流可以通过两种方式实现:使用 Lodash 库手写节流函数

2.1 使用 Lodash 库

Lodash 是一个非常流行的 JavaScript 工具库,提供了许多实用的函数,其中就包括 _.throttle 函数。_.throttle 函数可以将一个函数包装为一个节流函数,确保在指定的时间间隔内,最多只执行一次。

2.1.1 _.throttle 方法的参数说明

_.throttle 方法的签名如下:

_.throttle(func, [wait = 0], [options = {}])
  • func:需要节流的函数。
  • wait:时间间隔(单位为毫秒)。默认值为 0。
  • options:可选参数,用于配置节流行为。常用选项包括:
    • leading:布尔值,如果为 true,则在时间间隔开始时立即执行一次函数。默认值为 true
    • trailing:布尔值,如果为 true,则在时间间隔结束后执行一次函数。默认值为 true
2.1.2 示例代码
<body>
	<div style="height: 200px; width: 200px; background-color: pink;">
	</div>
	<script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
	<script>
		console.log('loaded');
		// 节流
		// 定义:在单位时间内,最多只执行一次事件的处理函数
		// 使用场景:滚动事件、鼠标移动事件、窗口大小调整等
		// 需求:鼠标在盒子上一滑动,里面的数字就发生变化 + 1

		// TODO.1 没做节流处理的代码
		// const box = document.querySelector('div');
		// let i = 1;
		// const mouseMove = () => box.innerText = i++;
		// box.addEventListener('mousemove', mouseMove);

		// TODO.2 进行节流处理(此处我们处理的方式是鼠标在盒子上移动,每500ms最多触发一次)
		/* 实现方式
		1. lodash 库提供的节流来处理
		2. 手写一个节流函数来处理
		*/

		// TODO.3 lodash 库 处理
		// 该库提供的 _.throttle(function, [wait = 0])函数,作用是在wait毫秒内最多调用一次function
		const box = document.querySelector('div');
		let i = 1;
		const mouseMove = () => box.innerText = i++;
		box.addEventListener('mousemove', _.throttle(mouseMove, 500)); // 此时每500ms最多触发一次加1事件
	</script>
</body>

在上面的代码中,我们使用了 Lodash 的 _.throttle 函数,将 mouseMove 函数包装为一个节流函数。只有在每 500 毫秒内,才会触发一次 mouseMove 函数。

2.2 手写节流函数

如果你不想使用 Lodash 库,也可以手写一个节流函数。手写节流函数的实现相对简单,但需要理解定时器的使用。

2.2.1 示例代码
function throttle(func, limit) {
	let inThrottle;
	return function() {
		const args = arguments;
		const context = this;
		if (!inThrottle) {
			func.apply(context, args);
			inThrottle = true;
			setTimeout(() => {
				inThrottle = false;
			}, limit);
		}
	};
}

const box = document.querySelector('div');
let i = 1;
const mouseMove = () => box.innerText = i++;
box.addEventListener('mousemove', throttle(mouseMove, 500));

在上面的代码中,我们定义了一个 throttle 函数,它接受两个参数:func 是需要节流的函数,limit 是时间间隔(单位为毫秒)。throttle 函数返回一个新的函数,每次触发事件时,都会检查是否在时间间隔内已经触发过函数。如果已经触发过,则不会再次触发,直到时间间隔结束。

三、Lodash 的 CDN 使用方法

以下是常用的 Lodash 库的 CDN 地址:

jsDelivr

  • 最新版本https://cdn.jsdelivr.net/npm/lodash/lodash.min.js
  • 指定版本https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js

unpkg

  • 最新版本https://unpkg.com/lodash/lodash.min.js
  • 指定版本https://unpkg.com/lodash@4.17.21/lodash.min.js

BootCDN

  • 最新版本https://cdn.bootcdn.net/ajax/libs/lodash.js/latest/lodash.min.js
  • 指定版本https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js

你可以根据自己的需求选择合适的 CDN 地址来引入 Lodash 库。

四、在 Vue 或 Next.js 项目中使用 Lodash

4.1 在 Vue 项目中使用 Lodash

  1. 安装 Lodash

    npm install lodash
    
  2. 在组件中使用 Lodash

    <template>
      <div @mousemove="throttledMousemove">
        {{ count }}
      </div>
    </template>
    
    <script>
    import _ from 'lodash';
    
    export default {
      data() {
        return {
          count: 0,
        };
      },
      methods: {
        mousemove() {
          this.count += 1;
        },
      },
      created() {
        this.throttledMousemove = _.throttle(this.mousemove, 500);
      },
    };
    </script>
    
    <style>
    div {
      height: 200px;
      width: 200px;
      background-color: pink;
    }
    </style>
    

4.2 在 Next.js 项目中使用 Lodash

  1. 安装 Lodash

    npm install lodash
    
  2. 在页面中使用 Lodash

    import _ from 'lodash';
    import { useState } from 'react';
    
    export default function Home() {
      const [count, setCount] = useState(0);
    
      const mousemove = () => {
        setCount(count + 1);
      };
    
      const throttledMousemove = _.throttle(mousemove, 500);
    
      return (
        <div onMouseMove={throttledMousemove}>
          {count}
        </div>
      );
    }
    

五、节流与防抖的区别

节流和防抖(Debounce)都是用于优化事件触发频率的技术,但它们的实现方式和应用场景有所不同。

  • 节流:在单位时间内,最多只执行一次事件的处理函数。适用于滚动事件、鼠标移动事件、窗口大小调整等场景。
  • 防抖:在单位时间内频繁触发事件时,只执行最后一次事件的处理函数。适用于输入框的实时验证、窗口大小调整等场景。

六、总结

节流是一种非常实用的优化技术,可以有效减少事件的触发频率,提高应用的性能和用户体验。你可以通过使用 Lodash 库的 _.throttle 函数,或者手写一个节流函数来实现节流。在实际开发中,根据具体需求选择合适的实现方式。

希望这篇文章能帮助你更好地理解和使用节流技术。如果你有任何问题或建议,欢迎在评论区留言!