什么是防抖和节流?如何理解它们并在不同的场景条件下灵活运用?

🙋‍♂️ 什么是防抖和节流?

防抖(Debouncing)和节流(Throttling)是两种常见的性能优化技术,常用于控制某些操作(例如事件处理器)的频率,从而减少资源消耗并提高性能。

防抖(Debouncing)

防抖是一种在事件被触发后等待一段时间,如果在等待时间内没有再次触发该事件,则执行事件处理器。如果在等待时间内再次触发事件,则重新开始等待。常用于避免短时间内频繁触发的事件处理,例如窗口调整大小、搜索框输入等。

示例代码(JavaScript)
function debounce(func, wait) {
    let timeout;
    return function(...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

// 示例用法
window.addEventListener('resize', debounce(() => {
    console.log('Window resized');
}, 300));

在这个示例中,当窗口大小变化时,只有在窗口大小停止变化后的300毫秒,console.log('Window resized') 才会被执行。

📹 视频演示(video)

防抖视频

节流(Throttling)

节流是一种在一定时间间隔内只允许函数执行一次,无论该时间间隔内事件被触发了多少次。常用于控制高频率触发的事件处理,例如滚动、鼠标移动等。

示例代码(JavaScript)
function throttle(func, limit) {
    let lastFunc;
    let lastRan;
    return function(...args) {
        const context = this;
        if (!lastRan) {
            func.apply(context, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(() => {
                if ((Date.now() - lastRan) >= limit) {
                    func.apply(context, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
}

// 示例用法
window.addEventListener('scroll', throttle(() => {
    console.log('Window scrolled');
}, 1000));

在这个示例中,当窗口滚动时,console.log('Window scrolled') 最多每隔1秒执行一次。

📹 视频演示(video)

节流视频

🏁 总结

  • 防抖:在事件停止触发后的指定时间内执行函数。适用于需要等用户停止操作后再处理事件的场景。
  • 节流:在指定时间间隔内最多执行一次函数。适用于需要限制函数执行频率的场景。

🙋‍♂️ 窗口滚动事件一定得用节流吗?不可以使用防抖吗?

窗口滚动事件使用节流和防抖都可以,但取决于具体需求和效果。

使用防抖处理滚动事件

防抖会在用户停止滚动后的一段时间才执行函数,这在某些场景下是有用的,例如:

  • 仅在用户停止滚动时加载数据或执行某些操作。
  • 避免在滚动过程中频繁执行函数,而仅在滚动结束时执行。
示例代码
window.addEventListener('scroll', debounce(() => {
    console.log('Scroll event detected after scrolling stops');
}, 200));

在这个示例中,只有当用户停止滚动200毫秒后,console.log('Scroll event detected after scrolling stops') 才会被执行。

使用节流处理滚动事件

节流会在用户滚动过程中每隔一段时间执行一次函数,这在需要频繁更新页面内容的场景下非常有用,例如:

  • 实时更新滚动进度条。
  • 在滚动过程中动态加载数据(如无限滚动)。
示例代码
window.addEventListener('scroll', throttle(() => {
    console.log('Scroll event detected with throttling');
}, 1000));

在这个示例中,console.log('Scroll event detected with throttling') 会在用户滚动过程中最多每隔1秒执行一次。

选择防抖还是节流

  • 防抖:适用于在用户停止滚动后执行操作。例如,停止滚动后加载更多内容或进行一次性计算。
  • 节流:适用于在滚动过程中需要持续执行操作。例如,实时更新界面元素或加载滚动区域内的内容。

🏁 总结

  • 滚动停止后的操作:使用防抖。
  • 滚动过程中的持续操作:使用节流。

根据具体需求选择适合的优化技术可以有效提高应用性能和用户体验。

🙋‍♂️ Vue3组合式 + TypeScript 写法

使用 Vue 3组合式 和 TypeScript语法, 实现窗口调整大小的防抖(debouncing)和滚动事件的节流(throttling)

1. 窗口调整大小的防抖(Debouncing)

<template>
  <div>
    <p>Resize the window and check the console for debounced resize events.</p>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

// 防抖函数
function debounce<T extends (...args: any[]) => void>(func: T, wait: number) {
  let timeout: ReturnType<typeof setTimeout>;
  return function(this: any, ...args: Parameters<T>) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), wait);
  };
}

// 防抖处理函数
const handleResize = debounce(() => {
  console.log('Window resized (debounced)');
}, 300);

// 注册和注销事件监听
onMounted(() => {
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
});
</script>

2. 滚动事件的节流(Throttling)

<template>
  <div>
    <p>Scroll the page and check the console for throttled scroll events.</p>
    <div style="height: 2000px;">Scroll content</div>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';

// 节流函数
function throttle<T extends (...args: any[]) => void>(func: T, limit: number) {
  let lastFunc: ReturnType<typeof setTimeout>;
  let lastRan: number | undefined;
  return function(this: any, ...args: Parameters<T>) {
    const context = this;
    if (!lastRan) {
      func.apply(context, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(() => {
        if ((Date.now() - lastRan) >= limit) {
          func.apply(context, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  };
}

// 节流处理函数
const handleScroll = throttle(() => {
  console.log('Scroll event detected (throttled)');
}, 1000);

// 注册和注销事件监听
onMounted(() => {
  window.addEventListener('scroll', handleScroll);
});

onUnmounted(() => {
  window.removeEventListener('scroll', handleScroll);
});
</script>

说明

  1. 防抖(Debouncing):

    • 实现:当窗口大小调整事件触发时,handleResize 函数会在300毫秒内没有进一步的调整后才执行。
    • 用法:当用户调整窗口大小时,防止过多频繁地处理事件,提升性能。
  2. 节流(Throttling):

    • 实现handleScroll 函数会在每1秒内最多执行一次,以控制滚动事件处理的频率。
    • 用法:减少滚动过程中处理事件的频率,优化性能和用户体验。

在 Vue 3 中使用 <script setup lang="ts"> 可以方便地处理生命周期事件,如组件挂载 (onMounted) 和卸载 (onUnmounted),以便正确地添加和移除事件监听器。

当然,你可以将上面的防抖节流函数进行封装公用方法,供组件或模块使用。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vinca@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值