【JS】手写防抖
防抖分为立即执行版本和非立即执行版本
代码示例
<!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>
</body>
<script>
/**
* @desc 函数防抖---“立即执行版本” 和 “非立即执行版本” 的组合版本
* @param func 需要执行的函数
* @param wait 延迟执行时间(毫秒)
* @param immediate---true 表立即执行,false 表非立即执行
**/
function debounce(func, wait, immediate) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timer = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener("mousemove",debounce(handle,1000,true)); // 调用立即执行版本
// window.addEventListener("mousemove", debounce(handle, 1000, false)); // 调用非立即执行版本
</script>
</html>
防抖函数是单例的
由于闭包的特性,timer 只有一份,如果两个地方使用同一个防抖函数,状态会共享
<html>
<head>
<title>自定义封装防抖</title>
</head>
<body>
<button onclick="debounceClick()">提交1</button>
<button onclick="debounceClick()">提交2</button>
</body>
<script>
function debounce(func, wait, immediate) {
let timer
return function() {
const context = this
const args = arguments
console.log(`timer = ${timer}`)
if(timer){
clearTimeout(timer)
}
if(immediate) {
const callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait);
if(callNow) {
func.apply(context, args)
}
} else {
timer = setTimeout(() => {
func.apply(context, args)
}, wait)
}
}
}
function click() {
// print current time
console.log(new Date().toString().split(' ')[4])
}
const debounceClick = debounce(click, 1000, true)
</script>
</html>
创建多个防抖函数
<html>
<head>
<title>自定义封装防抖</title>
</head>
<body>
<button onclick="debounceClick()">提交1</button>
<button onclick="debounceClick()">提交2</button>
<button onclick="debounceClick2()">提交3</button>
</body>
<script>
function debounce(func, wait, immediate) {
let timer
return function() {
const context = this
const args = arguments
console.log(`timer = ${timer}`)
if(timer){
clearTimeout(timer)
}
if(immediate) {
const callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait);
if(callNow) {
func.apply(context, args)
}
} else {
timer = setTimeout(() => {
func.apply(context, args)
}, wait)
}
}
}
function click() {
// print current time
console.log(new Date().toString().split(' ')[4])
}
const debounceClick = debounce(click, 1000, true)
const debounceClick2 = debounce(click, 1000, true)
</script>
</html>
vue
<script setup lang="ts">
const p = console.log
function debounce(func: Function, wait: number, immediate: boolean): Function {
let timer: any = null
return function() {
const context = this
const args = arguments
p(`timer: ${timer}`)
if(timer) {
clearTimeout(timer)
}
if(immediate) {
const callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait)
if(callNow) {
func.apply(context, args)
}
} else {
timer = setTimeout(() => {
func.apply(context, args)
}, wait)
}
}
}
function click() {
console.log(new Date().getTime().toString().split(' ')[4])
}
const debounceClick: Function = debounce(click, 1000, true)
const debounceClick2: Function = debounce(click, 1000, true)
</script>
<template>
<button @click="debounceClick">提交1</button>
<button @click="debounceClick">提交2</button>
<button @click="debounceClick2">提交3</button>
</template>
<style scoped>
</style>