原理: 存在一定的情况高频触发时间,如滚动,unblur ,快速点击等情况,不想频繁的触发相应的事件,则需要防抖函数来控制事件触发结束后来进行相应的回调 仅执行一次 其中使用了闭包来进行存储timer值,若不了解闭包可以看闭包详解 juejin.cn/post/684490…
简单的防抖函数
// func 回调函数 delay 延迟ms
export default function(func,delay){
//因使用es6模块语法 此时this指向undefined
let timer
return function(){
//此时的this指向调用者 window或者vue实例
let that = this
clearTimeout(timer)
timer = setTimeout(()=>{
func.apply(that)
})
}
}
稍微复杂一点的防抖函数
// func 回调函数 delay 延迟ms immediate 是否立即执行
export default function(func, delay=1000, immediate = false){
let timer
console.log(this)
return function(...args){
let that = this
if(immediate){
func.apply(that,args)
immediate = false
return
}
clearTimeout(timer)
timer = setTimeout(()=>{
func.apply(that,args)
},delay)
}
}
ts版本的防抖函数
/**
* 防抖函数
* @param func 执行函数
* @param delay 延迟时间 ms
* @param immediate 是否立即执行
*/
export default function (func: Function, delay: number, immediate: boolean = false): Function {
let timer: number | undefined
return function (this: unknown, ...args: any[]) {
let that = this
if (immediate) {
func.apply(that, args) // 确保引用函数的指向正确,并且函数的参数也不变
immediate = false
return
}
clearTimeout(timer)
timer = setTimeout(() => {
func.apply(that, args)
}, delay)
}
}
防抖节流一体函数
export default function (func,delay,options){
let timer
let defaultOption = {
debounce:true,
trailing: true,
leading: false,
}
}
vue中使用防抖函数
<template>
<div>
<h3>This is demo1</h3>
<p>
test debounce
<button type="button" @click="noDeounceFunc($event,'点击noDebounce')">noDeounce</button>
<button type="button" @click="debounceFunc($event,'点击Debonce')">debounce</button>
</p>
</div>
</template>
<script>
import debounce from "../utils/debounce.js";
export default {
methods: {
debounceFunc:debounce((event,msg)=>{
console.log(msg);
}, 2000),
noDeounceFunc:(event,msg)=> {
console.log(msg);
}
},
};
</script>
防抖节流通用函数 leading为true时,每隔delay触发一次时间。否则与防抖效果相同
export function debounce(func,delay,option){
return base(func,delay,Object.assign({},{
debounce:true,
},option))
}
export function throttle(func,delay,option){
return base(func,delay,Object.assign({},,{leading:true,debounce:false}option))
}
function base (func,delay = 2000,option){
let timer
let lastExecTime = 0
let defaultOption = {
leading: false,
debounce: false,
trailing: true,
}
const {leading, debounce, trailing} = Object.assign({},defaultOption,option);
return function(...args){
const that = this
const previous = +new Date() - lastExecTime
let isNotLeading = true
function exec(){
lastExecTime = +new Date()
func.apply(that,args)
}
function clear(){
timer = null
exec()
}
if (leading && ((!debounce && previous > delay) || (debounce && timer === null))) {
exec()
isNotLeading = false
}
if(timer){
clearTimeout(timer)
}
if(trailing && isNotLeading){
console.log(isNotLeading)
timer = setTimeout(debounce? clear: exec,delay)
}
}
}