vue项目中使用全局自定义指令实现防抖和节流,防止频繁调用接口

vue项目中使用全局自定义指令实现防抖和节流,防止频繁调用接口

一、防抖和节流的思想

防抖(Dedouncing):在一定时间范围内,如果同一事件多次被触发,只执行最后一次操作。也就是说,在防抖时间内持续触发某个事件,只有在事件触发停止一段时间后才会真正执行。打个比方:好比玩王者荣耀,你不断地点击回城键,但是只会执行最后一次回城事件。
防抖的应用场景很多,例如搜索框输入时进行搜索、窗口大小调整等,每次触发可能导致大量的资源被占用,使用防抖可以减少函数处理次数,提高性能。
具体实现方式:当事件持续触发时,一个定时器会重新开始计时,只有在定时器间隔超过阀值时,该事件才会得到响应。
节流(Throttling):在一定的时间间隔内,无论事件触发了多少次,都只执行第一次触发的事件。也就是说,每隔一段时间执行一次操作,而不管这段时间内事件触发了多少次。打个比方:好比玩王者荣耀,你不断地点击三个技能,但是技能是需要冷却时间的,只有在技能冷却时间到了,你才可以重新使用技能。**
节流的应用场景也很多,**例如鼠标滚动事件、页面元素的拖拽操作、异步请求等,在这些操作中,连续触发事件可能会导致大量的资源被占用,使用节流可以减小函数的处理频率,提高性能。

具体实现方式:设置一个定时器,在规定的时间内只执行一次操作。如果该时间内事件再次被触发,则不会做任何操作,等规定的时间到了,只执行第一次触发的事件。

二、防抖和节流的代码

1.防抖

<!DOCTYPE html>
<html lang="en">

<head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>防抖</title>
</head>

<body>
      <button>点击</button>
      <script>
            let btn = document.querySelector('button')
            function debounce(func, delay) {
                  let timer = null;
                  return function () {
                        if (timer) {
                              clearTimeout(timer);
                        }
                        timer = setTimeout(() => {
                              func.apply(this, arguments);//执行回调函数,apply()改变this,指向事件源(button)
                              timer = null;
                        }, delay);
                  };
            }
            btn.addEventListener('click', debounce(function (e) {
                  console.log('点累了吗?累了,过了300毫秒我要执行了!',e.target);
            }, 300))
      </script>
</body>

</html>

其中 func 是需要进行防抖操作的函数,func=>function (e) { console.log('可以执行了!',e.target); },delay 是设置的防抖间隔时间。在该函数内部,每当事件被重复触发时都会重新计时,只有不再触发且延迟时间后才会真正执行最后一次触发的事件。

实际应用中,可以将需要防抖的函数作为参数传递给触发的函数,例如:

 btn.addEventListener('click', debounce(function (e) {
                  console.log('点累了吗?累了,过了300毫秒我要执行了!',e.target);
       }, 300))

2.节流

<!DOCTYPE html>
<html lang="en">

<head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>节流</title>
</head>

<body>
      <button>获取验证码</button>
      <script>
            let btn = document.querySelector('button')
            function throttle(fn, deplay) {
                  let timer = null
                  return function () {
                        if (!timer) {
                              timer = setTimeout(() => {
                                    fn.apply(this, arguments)
                                    timer=null
                              }, deplay)
                        }
                  }
            }
            btn.addEventListener('click', throttle(function (e) {
                  console.log('等2s我再执行!',e.target);
            }, 2000))
      </script>
</body>

</html>

这里 fun 同样是需要进行节流操作的函数,deplay是规定的时间间隔。创建一个变量 timer 用于记录上一次执行的定时器ID;返回一个匿名函数,在该函数中使用 if (!timer) 判断是否存在上一次定时器ID;如果不存在,则在当前上下文中触发定时器,并设定定时器计时结束后执行要进行节流控制的目标函数;在定时器完成之后,将上一次定时器ID清空并返回函数,以便下一轮调用。
使用方法同样是将需要节流的函数作为参数传递给触发的函数:

  btn.addEventListener('click', throttle(function (e) {
                  console.log('等2s我再执行!',e.target);
  }, 2000))

三、vue项目中使用防抖和节流

我这里只做按钮的防抖功能,防止多次调用接口
**1.**首先在项目中创建一个directive.js文件,放在哪根据你的项目具体情况来决定,我一般是放在utils中。

import Vue from 'vue'
/*
  按钮防抖自定义指令
*/
Vue.directive('debounce', {
  inserted: function (el, binding) {
    let timer = null
    el.addEventListener('click', () => {
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      timer = setTimeout(() => {
        binding.value()
      }, parseInt(binding.arg || 500))
    })
  }
})

解释:
1.binding.value()
binding.value()是只有这样引入<el-button v-debounce:500="buttonDebounce">按钮</el-button>才会有这个value()方法,如果你只是单独地引入<el-button v-debounce @click="buttonDebounce">按钮</el-button>,则不会有value()这个方法的,binding.value()这个方法是我们绑定的点击事件。
2.binding.arg
binding.arg接收<el-button v-debounce:500="buttonDebounce">按钮</el-button>传过来的500,如果不传,这样引入的话<el-button v-debounce @click="buttonDebounce">按钮</el-button>,binding.arg的值的undefined,有值的话类型是一个string类型,为什么要加parseInt,因为binding.arg的值是一个string类型,所以转换一下。大家也可以尝试打印一下看看。
2.在main.js中引入directive.js文件就可以了

import '@/utils/directive.js'

在 template 模板中使用 v-debounce 指令,绑定防抖函数

<el-button v-debounce:500="buttonDebounce">按钮</el-button>

其中:500是我们用来自定义时间参数的,对应directive.js中binding.arg,表示设置防抖时间为500毫秒。可以根据需要进行调整。
这样,点击按钮时就会触发 buttonDebounce 方法,并进行防抖操作,从而达到了防抖的效果。可以将这个自定义指令封装成一个单独文件,在需要使用的地方引入即可,方便复用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值