万万Vue中使用防抖Or节流还有这么多细节

万万Vue中使用防抖Or节流还有这么多细节

前言

防抖、节流函数在工作中经常用到,但是在使用的时候,经常都是按照网上CV就完成了,没去考虑很多细节性的问题,今天就来好好研究一下。

vue中防抖和节流

通常情况下,节流和防抖都是写成公共的方法,因此本文都的节流和防抖,就以公共方法为例。

目前在vue2中,有两种防抖和节流的使用方法

第一种方法加防抖和节流的方式:

javascript 复制代码
      // 正确使用示例
      handleInput: debounce((e) => {
        console.log(e);
      }, 1000),
      // 错误使用示例
      handleInput() {
        return debounce((() => {
          console.log('方法执行了');
        }), 1000)();
      },

第二种方法加防抖和节流的方式:这种方法需要在created或者mounted中去声明一个变量来存储这个方法,然后在下面的方法调用再去使用这个方法

javascript 复制代码
    mounted() {
      // 声明方法,利用一个变量存储
      this.debounceInput = debounce((e) => {
        console.log(e);
      }, 3000)
    },
    // 使用方法
    handleInput() {
    	this.debounceInput();
    },

细节

上面我们已经了解了使用的方法,那么接下来就是重头戏了,了解一下这两种写法有什么区别,首先是第一种

首先来运行一下,我在防抖内部加一个console.log语句

javascript 复制代码
export const debounce = (func, time) => {
    let timer = null;
    console.log(timer, '防抖函数内部的timer');
    return (...args) => {
        console.log(args);
        if(timer) clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(this, args)
        }, time)
    }
}

然后以正确示例的代码执行一下

javascript 复制代码
// 正确使用示例
handleInput: debounce((e) => {
	console.log(e);
}, 1000),

动图中我们可以看到,我刷新后没有执行任何操作(注意没有执行任何操作),但是debounce却执行了,这意味这什么?

这时候我们其实防抖函数已经把return 函数赋值给我们handleInput这个方法了

这时候其他我们的代码是这样的形式,这里可能会有误解那么timer这些变量哪里来,其实人家还是在util中执行我只是拿过来方便大家理解

那么从代码中我们就可以看在一开始我们debounce其实就已经把结果返回给我们了

这时候我们每次调用其实就是执行deboucne里return的内容

这时候timer也不会重复声明所以说,防抖有效,那么来测试一下

javascript 复制代码
      handleInput: debounce((e) => {
        console.log(e, 'debounce回调的方法');
      }, 1000),
      <el-input v-model="ruleForm.name" @input="handleInput"></el-input>

这里绑定了input事件,我们应该是重复触发就重新计时,如果计时1秒后没有重新触发就输出console.log

那么我们来看一下这种方法为什么不行

javascript 复制代码
      // 错误使用示例
      handleInput() {
        return debounce((() => {
          console.log(e, 'debounce回到的方法');
        }), 1000)();
      },

先看执行效果

如图所示造成如果结果的原因就是,我们每次执行handleInput都会把debounce内容全部的函数执行一次,但是我们想到仅仅的debounce内部的return的方法执行

如果红框内所示的内容,但是我们如果放到方法里直接执行显然是不行的,所以就有了第二种

第二种方法: 其实第二种方法就是在生命周期中,先把调用一次,存储到变量中然后拿到debounce返回的方法

javascript 复制代码
    mounted() {
      this.debounceInput = debounce((e) => {
        console.log('debounce回调的方法');
      }, 3000)
    },
    // 使用方法
    handleInput() {
    	this.debounceInput();
    },

这里我们看一下效果

可以看到防抖的效果还是有的(我这里设置了3秒后回调)

那么我们来看一下debounceInput里的内容是什么

scss 复制代码
(...args) => {
    // console.log(args);
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(undefined, args);
    }, time);
  }

结果也如我们所料

那么两种方法有什么区别吗?

其实两个区别只有一个第一种在debounce的时候无法访问this

如果说debounce需要访问当前this的时候就无法访问,同时time也是固定的

我将代码改成以下形式

javascript 复制代码
      handleInput: debounce((e) => {
        console.log(e, 'debounce回到的方法');
      }, this.delay),

运行就报错了,所以如果说需要在debounce中访问this或者当前组件的变量,推荐使用第二种方法

相关推荐
hj5914_前端新手14 分钟前
javascript基础- 函数中 this 指向、call、apply、bind
前端·javascript
薛定谔的算法19 分钟前
低代码编辑器项目设计与实现:以JSON为核心的数据驱动架构
前端·react.js·前端框架
Hilaku29 分钟前
都2025年了,我们还有必要为了兼容性,去写那么多polyfill吗?
前端·javascript·css
yangcode34 分钟前
iOS 苹果内购 Storekit 2
前端
LuckySusu35 分钟前
【js篇】JavaScript 原型修改 vs 重写:深入理解 constructor的指向问题
前端·javascript
LuckySusu36 分钟前
【js篇】如何准确获取对象自身的属性?hasOwnProperty深度解析
前端·javascript
LuckySusu40 分钟前
【js篇】深入理解 JavaScript 作用域与作用域链
前端·javascript
LuckySusu40 分钟前
【js篇】call() 与 apply()深度对比
前端·javascript
LuckySusu44 分钟前
【js篇】addEventListener()方法的参数和使用
前端·javascript
该用户已不存在1 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net