Javascript函数防抖与节流的理解以及在vue和原生js中的使用

本文详细介绍了JavaScript中的函数防抖(debounce)和节流(throttle)的概念、实现原理、使用场景以及在Vue和原生JS中的应用实例。通过函数防抖和节流,可以有效降低频繁触发事件导致的计算负担,提高应用性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

防抖和节流的目的都是为了减少不必要的计算,不浪费资源,只在适合的时候再进行触发计算。

一、函数防抖(debounce)

1.定义: 事件触发停止一定时间后才会执行响应的函数,期间如果重复调用动作,重新计算时间。类似于,按下一个弹簧,只有你松手的时候弹簧才会弹起。本质上是将多次操作合并为一次操作。可用一个定时器维护,事件触发后wait时间内如果事件重复触发,那么取消当前定时器,重新设置一个时延为wait的定时器。

2.实现原理
函数防抖的基本思想是设置一个定时器,在指定时间间隔内运行代码时清除上一次的定时器,并设置另一个定时器,直到函数请求停止并超过时间间隔才会执行。

3.使用场景
文本框输入搜索(连续输入时避免多次请求接口)

4.代码实现

/**
 * 函数防抖
 */
export function debounce(fn, t) {
  // 记录上一次的延时器
  var timer = null;
  var delay = t || 200;
  return function() {
    var args = arguments;
    var that = this;
    // 清除上一次延时器
    clearTimeout(timer)
    timer = setTimeout(function() {
        fn.apply(that,args)
    }, delay);
  }
}

二、函数节流
1.定义
规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。

2.实现原理
其原理是用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 规定时间段,如果是,则执行,并更新上次执行的时间戳。

3.使用场景
resize、scroll、mousemove等事件触发监听

4.代码实现

    /**
     * 函数节流
     */
    export function throttle(fn,t){
      var lastTime;
      var timer;
      var delay = t || 200;
      return function() {
        var args = arguments;
        // 记录当前函数触发的时间
        var nowTime = Date.now();
        if (lastTime && nowTime - lastTime < delay) {
          clearTimeout(timer);
          timer = setTimeout(function () {
            // 记录上一次函数触发的时间
            lastTime = nowTime;
            // 修正this指向问题
            fn.apply(this, args);
          }, delay);
        }else{
          lastTime = nowTime;
          fn.apply(this, args);
        }
      }
    } 

函数防抖节流在Vue中的使用。

1.在libs文件夹下创建public.js文件

完整代码如下:

/**
 * 函数防抖
 */
export function debounce (fn, t) {
  // 记录上一次的延时器
  var timer = null
  var delay = t || 200
  return function () {
    var args = arguments
    var that = this
    // 清除上一次延时器
    clearTimeout(timer)
    timer = setTimeout(function () {
      fn.apply(that, args)
    }, delay)
  }
}
/**
 * 函数节流
 */
export function throttle (fn, t) {
  var lastTime
  var timer
  var delay = t || 200
  return function () {
    var args = arguments
    // 记录当前函数触发的时间
    var nowTime = Date.now()
    if (lastTime && nowTime - lastTime < delay) {
      clearTimeout(timer)
      timer = setTimeout(function () {
        // 记录上一次函数触发的时间
        lastTime = nowTime
        // 修正this指向问题
        fn.apply(this, args)
      }, delay)
    } else {
      lastTime = nowTime
      fn.apply(this, args)
    }
  }
}

2.在你需要的页面中引用

    import { throttle,debounce } from '@/libs/public.js'

3.在组件中使用

<template>
<li
class="content-box"
 v-for="(list,index) in filterData"
 :key="index"
 @click="changeColor2(list,index)"
>
</li>
</template>

methods: {

changeColor2: throttle(function(list,index) {
//do something
},100)
}

解释一下:throttle是引用了节流这个函数,在function(list,index)里面可以传递参数,100是以毫秒为单位的时间

原生使用

函数防抖
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。如下面这段代码,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。

一个防抖的例子

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
          body{
            height: 5000px;
          }
        </style>
      </head>
      <body>
        <script>
          //防抖函数、fn(处理函数),wait(自定义定时器时间)
          function debounce(fn, wait) { 
            var timeout = ""; //声明变量timeout复制为空字符串
            return function() {//返回匿名函数
              if(timeout !== ""){//如果timeout不为空
                clearTimeout(timeout);//清除timeout定时器
              }
              timeout = setTimeout(fn, wait);//重新给timeout赋值为fn我处理函数,wait为定时周期的一次性定时器
            }
          }
          // 处理函数
          function handle() {
            console.log(Math.random());
          }
          // 滚动事件
          window.addEventListener('scroll', debounce(handle, 1000));//为window的scroll滑动事件绑定防抖函数
        </script>
      </body>
    </html>

代码执行路线是:

1、页面初始化,渲染页面,执行代码
2、调用debounce函数,声明一个变量timeout,并赋值为空字符串。返回一个匿名函数,通过addEventListener绑定给window的scroll(滑动事件)
3、触发window的scroll(滑动事件)
4、进入window的scroll的处理函数(调用debounce函数返回的那个匿名函数)。
5.1、如果timeout不为空,清除timeout定时器,重新给timeout赋值为fn我处理函数,wait为定时周期的一次性定时器。
5.2、如果timeout为空,重新给timeout赋值为fn我处理函数,wait为定时周期的一次性定时器。
6、再次触发window的scroll(滑动事件),重复步骤4和步骤5
7、停止触发,执行一遍步骤4和步骤5
8、执行timeout一次性定时器,调用handle函数进行处理

函数节流------》定时器+时间戳

所以我们就把事件戳的有点和定时器的有点结合起来,变成下面的方案

    var throttle = function(func, delay) {
      var timer = "";
      var startTime = Date.now();
      return function() {
        var curTime = Date.now();
        var remaining = delay - (curTime - startTime);
        var context = this;
        var args = arguments;
        clearTimeout(timer);
        if (remaining <= 0) {
          func.apply(context, args);
          startTime = Date.now();
        } else {
          timer = setTimeout(func, remaining);
        }
      }
    }
    function handle() {
      console.log(Math.random());
    }
    window.addEventListener('scroll', throttle(handle, 1000));
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值