文章目录
<div id="content"
style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;">
</div>
<script>
let num = 1;
const content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
content.onmousemove = count;
</script>
实现效果:
防抖
所谓防抖,就是指触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
非立即执行函数:
触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
实现方法: 利用定时器,在函数第一次调用时,设定一个定时器,之后调用时发现已经存在定时器就清空之前的定时器,并重新设定一个新的定时器。如果存在没有被清空的定时器,当定时器计时结束后触发函数执行
// 每次触发事件时,无论如何先清空计时器,再开新计时器
function debounce(func, wait) {
let timeout;
return function () {
const context = this;
const args = [...arguments];
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
content.onmousemove = debounce(count,1000);
实现效果:
立即执行函数:
触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
为了提高用户体验,往往第一次调用的时候是需要立马执行函数的。
实现方法: 需要在原来的实现上加上第一次触发立即执行的功能。
function debounce(func,wait) {
let timeout;
return function () {
const context = this;
const args = [...arguments];
if (timeout) clearTimeout(timeout);
const callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
content.onmousemove = debounce(count,1000);
实现效果:
节流
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。 节流会稀释函数的执行频率。
时间戳法:
在持续触发事件的过程中,函数会立即执行,并且每 ns 执行一次。
实现方法: 通过时间戳来记录函数调用时刻,通过计算当前调用时间戳与上次调用的时间戳的时间差来判断是否已达到规定等待时间。如果是,就执行函数,并更新上次调用时间戳。否则,忽略此次调用。
function throttle(func, wait) {
var previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
content.onmousemove = throttle(count,1000);
实现效果:
定时器法:
在持续触发事件的过程中,函数不会立即执行,并且每 ns 执行一次,在停止触发事件后,函数还会再执行一次。
实现方法: 函数调用时,判断当前是否有定时器存在,若定时器存在,就不执行,知道wait时间后,定时器执行函数,并且清空定时器,继续设置下一个定时器。
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimezhixingout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
content.onmousemove = throttle(count,1000);
实现效果:
区别:
- 时间戳版的函数触发是在 时间段内开始 的时候
- 定时器版的函数触发是在 时间段内结束 的时候。
防抖与节流的比较
相同点:
- 都可以通过使用 setTimeout 实现
- 目的都是,降低回调执行频率,节省计算资源
不同点:
- 防抖,在一段连续操作结束后,处理回调,利用clearTimeout 和 setTimeout实现。节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
- 防抖关注一定时间连续触发的事件只在最后执行一次。节流侧重于一段时间内只执行一次
应用场景:
函数防抖:
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染
函数节流:
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
参考文章: