# 手写节流
# 定义
n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
# 代码实现
设计思路:我们可以设计一种类似控制阀门一样定期开放的函数,事件触发时让函数执行一次,然后关闭这个阀门,过了一段时间后再将这个阀门打开,再次触发事件。
刚开始valid为true,然后将valid重置为false,进入了定时器,在定时器的时间期限之后,才会将valid重置为true,valid为true之后,之后的点击才会生效
在定时器的时间期限内,valid还没有重置为true,会一直进入return,就实现了在N秒内多次点击只会执行一次的效果
function throttle(fn, delay){
let valid = true;
return function(){
if(valid) { //如果阀门已经打开,就继续往下
setTimeout(()=> {
fn.apply(this, arguments);//定时器结束后执行
valid = true;//执行完成后打开阀门
}, delay)
valid = false;//关闭阀门
}
}
}
# 生产实践
拖拽元素

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>throttle</title>
</head>
<body>
<p>throttle</p>
<div
id="div1"
draggable="true"
style="width: 100px; height: 50px; background-color: #ccc; padding: 10px"
>
可拖拽
</div>
<script>
// function throttle(fn, delay = 100) {
// let timer = 0
// return function () {
// if (timer) return
// timer = setTimeout(() => {
// fn.apply(this, arguments)
// timer = 0
// }, delay)
// }
// }
function throttle(fn, delay = 500) {
let valid = true
return function () {
if (valid) {
//如果阀门已经打开,就继续往下
setTimeout(() => {
fn.apply(this, arguments) //定时器结束后执行
valid = true //执行完成后打开阀门
}, delay)
valid = false //关闭阀门
}
}
}
const div1 = document.getElementById('div1')
div1.addEventListener(
'drag',
throttle((e) => {
console.log('鼠标的位置', e.offsetX, e.offsetY)
})
)
</script>
</body>
</html>