从零开始vue3+vite+ts+pinia+router4后台管理(6)-全局自定义指令实现节流与防抖
什么是节流和防抖
节流:即某个时间内该函数只执行一次,大白话的理解就是你2秒内最快速度频繁去点击一个按钮 按钮的函数在2秒内只执行一次
防抖:防抖是指当你触发一个事件的时候,它的回调不会立即执行,而是在 n 秒之后执行,但当在这 n 秒之内你又触发了这个事件,则会重新计时,也就是你还需要再等 n 秒才会执行,大白话的理解就是 你玩游戏回城的时候,只要你点击回城就会重新开始计时,
多次触发事件只执行一次
是防抖,按规定的频率
执行是节流
函数的方式实现节流防抖
看效果 点击节流
输入防抖
逻辑代码
<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);
全局注册
import directive from "@/directive/index";// 引入全局自定义指令
app.use(directive);//注册全局自定义指令
效果图