场景:限制事件触发频率,每隔多久执行一次,比如列表滚动事件监听是否滑动到底部 概念:触发事件会以固定频率触发,无论期间触发多少次 实现:事件戳和定时器;
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container{
width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var count = 1;
var container = document.getElementById('container');
function getUserAction() {
container.innerHTML = count++;
};
container.onmousemove = getUserAction;
</script>
</body>
</html>
以上代码表明div盒子中鼠标移动多少次就执行多少次数字累加,频率非常快。 场景还是和防抖一样的案例场景来介绍。
时间戳实现
获取每次事件触发的时间戳,和上次触发事件的时间戳作对比,如果这个差值大于我们设定的时间间隔,才执行事件,同时将初始化的时间戳更新为最新的时间戳[这里同样是需要一个变量previous来存储之前的时间戳,以和下一次执行的时间戳作比较判断间隔是否超过,超过则执行]。
function throttle(func, wait) {
let previous = 0;
retutrn function(){
let now = new Date(); // 获取当前时间戳,值为一个当前时间到1970 年 1 月 1 日(UTC)起经过的毫秒数。
if(now - previous > wait) { // 第一次就会执行
func.apply(this, arguments);
previous = now; // 将本次执行事件戳和下次执行事件时间戳作比较(即用来存储上一次的时间戳,同样的是利用了闭包)
}
}
}
调用
container.onmousemove = throttle(getUserAction, 1000)
定时器实现
function throttle(func, wait) {
let timeout = null;
return function(){
if(!timeout) {
timeout = setTimeout(()=>{
timeout = null;
func.apply(this, arguments)
}, wait);
}
}
}
触发事件后在延迟wait毫秒后执行,在事件执行的时候,timeout在定时器的回调中被重置为了null中,下一次事件触发又会进入!timeout判断中给timeout赋新的定时器(即让事件在下次执行)
两种实现方式方式的区别:时间戳是会立即执行,且最后一次不执行,定时器版本是会非立即执行,且最后一次会执行