万万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或者当前组件的变量,推荐使用第二种方法

相关推荐
課代表1 分钟前
JavaScript 二维数组的三种定义与初始化方法
javascript·初始化·二维数组·多维数组·动态数组·循环遍历·数组合并
鸡吃丸子1 小时前
Next.js 入门指南
开发语言·javascript·next.js
罚时大师月色1 小时前
Vue+ts 如何实现父组件和子组件通信
javascript·vue.js·ecmascript
漂流瓶jz1 小时前
快速定位源码问题:SourceMap的生成/使用/文件格式与历史
前端·javascript·前端工程化
samroom1 小时前
iframe实战:跨域通信与安全隔离
前端·安全
fury_1232 小时前
vue3:数组的.includes方法怎么使用
前端·javascript·vue.js
weixin_405023372 小时前
包资源管理器NPM 使用
前端·npm·node.js
宁&沉沦2 小时前
Cursor 科技感的登录页面提示词
前端·javascript·vue.js
Dragonir2 小时前
React+Three.js 实现 Apple 2025 热成像 logo
前端·javascript·html·three.js·页面特效