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

相关推荐
三十_A3 小时前
如何正确实现圆角渐变边框?为什么 border-radius 对 border-image 不生效?
前端·css·css3
kgduu3 小时前
js之事件系统
javascript
小满zs3 小时前
Next.js第十三章(缓存组件)
前端
前端老宋Running4 小时前
“受控组件”的诅咒:为什么你需要 React Hook Form + Zod 来拯救你的键盘?
前端·javascript·react.js
风止何安啊4 小时前
拿捏 React 组件通讯:从父子到跨组件的「传功秘籍」
前端·react.js·面试
阿蒙Amon4 小时前
JavaScript学习笔记:7.数字和字符串
javascript·笔记·学习
懒得不想起名字4 小时前
将flutter打成aar包嵌入到安卓
前端
Highcharts.js4 小时前
官方文档|Angular 框架集成 Highcharts Dashboards
前端·javascript·angular.js·highcharts·看板·使用文档·dashboards
韭菜炒大葱4 小时前
React 新手村通关指南:状态、组件与魔法 UI 🧙‍♂️
前端·javascript·react.js
Dwzun4 小时前
基于SpringBoot+Vue的二手书籍交易平台系统【附源码+文档+部署视频+讲解)
java·vue.js·spring boot·后端·spring·计算机毕业设计