从零开始vue3+vite+ts+pinia+router4后台管理(6)-全局自定义指令实现节流与防抖

639 阅读2分钟

从零开始vue3+vite+ts+pinia+router4后台管理(6)-全局自定义指令实现节流与防抖

代码gitee地址

在线预览

什么是节流和防抖

节流:即某个时间内该函数只执行一次,大白话的理解就是你2秒内最快速度频繁去点击一个按钮 按钮的函数在2秒内只执行一次

防抖:防抖是指当你触发一个事件的时候,它的回调不会立即执行,而是在 n 秒之后执行,但当在这 n 秒之内你又触发了这个事件,则会重新计时,也就是你还需要再等 n 秒才会执行,大白话的理解就是 你玩游戏回城的时候,只要你点击回城就会重新开始计时,

多次触发事件只执行一次是防抖,按规定的频率执行是节流

函数的方式实现节流防抖

看效果 点击节流

6e25f254-811f-41f3-8374-4ba9b07dd0f4

输入防抖

a1480b1b-2b74-4187-95bf-95c240d472ae

逻辑代码

<template>
  <div class="app-container">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>函数的方式实现节流防抖</span>
        </div>
      </template>
      <el-button @click="throttleBtn" type="primary">节流点击</el-button>
      <br/>
      <br/>
      <el-input v-model="inputValue" @input="debounceInput" placeholder="输入防抖"  clearable />
    </el-card>
  </div>
</template>
<script setup lang="ts">
import {ref} from "vue";
const inputValue = ref("")
const throttle  = ref(null)//节流
const debounce  = ref(null)//防抖
const throttleBtn = () =>{
  if(throttle.value){ //判断setTimeout()定时器在两秒内存在否,存在就返回什么都不做
    return
  }else{//如果定时器不存在,就创建一个定时器
    console.log("我两秒钟只能被执行一次")
    throttle.value = setTimeout(()=>{
      throttle.value = null //两秒后清除定时器,等待下一次的点击
    },2000)
  }
}
const debounceInput = () =>{
  clearTimeout(debounce.value) //每次都需要先清空定时器
  debounce.value = setTimeout(()=>{ //定时器函数,2秒后执行
    console.log("每次调用我两秒后才能执行"+inputValue.value)
  },2000)
  //整个逻辑就是每一次点击都先清空计时器,让上一次的计时失效,当不在点击时就会执行
  //最后一次定时函数
}
</script>

全局自定义指令实现节流防抖

binding(DirectiveBinding):一个包含指令信息的对象。(例如:包含指令的名称、值、参数,函数对象等等)

directive.index.ts

// 节流
// 防止按钮多次点击,多次请求
//binding(DirectiveBinding):一个包含指令信息的对象。(例如:包含指令的名称、值、参数等等)
import {App, DirectiveBinding} from "vue";

export default (app: App) => {
    app.directive("throttle", {
        mounted(el: HTMLElement, binding: DirectiveBinding) {
            console.vlog(binding);
            const time = binding.value ? binding.value : 2000
            el.timer = null
            el.addEventListener('click', () => {
                el.disabled = true
                if (el.timer !== null) {
                    clearTimeout(el.timer)
                    el.timer = null
                    el.disabled = true
                }
                el.timer = setTimeout(() => {
                    el.disabled = false
                }, time)
            })
        }
    })
    // // 输入框防抖
    app.directive("debounce", {
        mounted(el: HTMLElement, binding: DirectiveBinding) {
            //binding.value.time这是输入框传过来的时间
            const time = binding.value.time ? binding.value.time : 1000
            //binding.value.func 这是输入框传过来的方法
            const func = binding.value ? binding.value.func : null
            el.timer = null
            el.addEventListener('input', () => {
                console.log(binding);
                if (el.timer !== null) {
                    clearTimeout(el.timer)
                    el.timer = null
                }
                el.timer = setTimeout(() => {
                    func && func()
                }, time)
            })
        }
    })
}

vue文件中使用

<el-button v-throttle @click="testThrottle" type="primary">节流点击</el-button>
<br/>
<br/>
<el-input v-model="inputValue" v-debounce="{ time: 3000, func: () => testDebounceInput() }"   placeholder="输入防抖"  clearable />

directive.index.ts代码中 binding.value.time这是输入框v-debounce传过来的时间,binding.value.func 这是v-debounce输入框传过来的方法testDebounceInput

浏览器打印一下可以看到console.log(binding);

image-20231016170934096

全局注册

import directive from "@/directive/index";// 引入全局自定义指令
app.use(directive);//注册全局自定义指令

效果图

2936d4a6-6ec1-4841-a1a1-1137a95a2851