什么是防抖
事件响应函数在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间;当预定的时间内没有再次调用该函数,则执行该函数。
防抖做什么
防止某些函数的频繁调用,保证页面的稳定流畅和数据准确性。
一个小的例子
使用 underscore 的防抖功能来测试一下效果。
在页面中直接导入cdn即可。
https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js
未防抖时的样子
将下面内容粘贴到一个HTML的body标签中。
<div id="container" style="width:100%;height:200px;line-height:200px;text-align:center;color:#fff;background-color:#444;font-size:30px;"></div>
<script>
let count = 0;
let container = document.querySelector("#container");
// 此处为高频调用函数
function doSomething() {
container.innerHTML = count++;
}
container.onmousemove = doSomething;
</script>
这段代码会生成一个灰色框,只要鼠标在其内部移动,就会调用 doSomething
函数,导致数字不断增长。
使用防抖
同样地,将下面内容粘贴到一个新的HTML的body标签中。
<div id="container" style="width:100%;height:200px;line-height:200px;text-align:center;color:#fff;background-color:#444;font-size:30px;"></div>
<script src="https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js"></script>
<script>
let count = 0;
let container = document.querySelector("#container");
// 此处为高频调用函数
function doSomething() {
container.innerHTML = count++;
}
container.onmousemove = _.debounce(doSomething, 300);
</script>
这里导入了
underscore
库,这个库会导出一个_
的对象,它包含一个debounce
方法,该方法的作用就是防抖。第一个参数是函数原型,第二个参数是响应时间,另外还可以设置是否立即执行,如果是,传入true
。这里我们设置300ms后响应。
这次运行后,可以发现当鼠标移动时,不再一味地增加,而是当鼠标静止或移出后一段时间(300ms)才会响应。
手动实现防抖函数
如果仅仅使用防抖函数,导入一个库是得不偿失的,因为防抖函数本身并不大,所以可以手写一个。
function debounce(func, wait, immediate) {
let timeout, result;
var debounced = function() {
// 获取上下文,关联this的指向
let context = this;
// 获取所有参数
const args = arguments;
// 每次防抖都清除定时器,然后设置一个新的定时器。
if (timeout) clearTimeout(timeout);
// 区别是否立即执行
if (immediate) {
// 如果立即执行,需要一个变量控制重复执行。这里利用timeout取反,可以控制效果
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
// 立即执行
if (callNow) result = func.apply(context, args);
} else {
// 不立即执行,则正常定时器等待即可
timeout = setTimeout(function() {
result = func.apply(context, args);
}, wait);
}
// 返回调用函数的结果
return result;
}
// 设置一个清除函数,可以手动控制取消防抖函数的执行。
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
}
return debounced;
}
文章评论