防抖:
事件响应函数在一定时间后执行,如果在这段时间内再调用,则重新计算执行时间;实现原理为设置一个定时器,约定在xx毫秒后再触发事件处理,每次触发事件都会重新设置计时器。
防抖应用场景:
scroll事件滚动触发,搜索框输入查询,表单验证,按钮提交事件,浏览器窗口缩放,resize事件。
为什么要防抖?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.content {
width: 800px;
height: 400px;
background-color: aqua;
margin: 100px auto;
}
</style>
</head>
<body>
<div class="content"></div>
<script>
// 频繁触发
let count = 0;
let content = document.querySelector('.content');
function doSome() {
content.innerHTML = count++;
}
content.onmousemove = doSome;
</script>
</body>
</html>
上面的代码想要实现功能:当鼠标移入到content里面,让count+1。但是真实实现的功能是鼠标移动一下count就会进行+1操作。比如实现一个搜索框功能,如果用户每输入一个字,就向服务器提交一次请求,这会页面出现卡顿,影响用户体验。而我们想要实现的是用户输入完内容,才向用户提交请求。这时就用到了防抖。
一个防抖和节流的插件underscore.js,可以实现函数的防抖和节流。
使用方法:
先引入js文件,然后使用_.debounce(函数名, 延迟时间,是否立即执行(默认为true))实现
content.onmousemove = _.debounce(doSome, 1000);
手写一个防抖函数debounce.js
// 防抖的函数
function debounce(func, wait, immediate) {
let timeout, result;
let decounced = function() {
let that = this;
let args = arguments;
if (timeout) { clearTimeout(timeout); }
if (immediate) {
let callNow = !timeout;
timeout = setTimeout(() => {
callNow = null;
}, wait)
// 立即执行
if (callNow) {
result = func.apply(that, args)
}
} else {
// 不会立即执行
timeout = setTimeout(function() {
// 改变this指向,使其指向调用者
// 拿到函数中的实参(event指向)
func.apply(that, args)
}, wait);
}
return result;
}
decounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
}
return decounced
}
该函数直接引用,即可使用,此外也实现了取消防抖的功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.content {
width: 800px;
height: 400px;
background-color: aqua;
margin: 100px auto;
}
</style>
</head>
<body>
<div class="content"></div>
<button>取消防抖</button>
<script src="./debounce.js"></script>
<script>
// 频繁触发
let count = 0;
let content = document.querySelector('.content');
let btn = document.querySelector('button')
function doSome() {
content.innerHTML = count++;
return 'hhhhh'
}
let doS = debounce(doSome, 10000);
// 点击按钮取消防抖
btn.onclcik = function() {
doS.cancel()
}
content.onmousemove = doS;
</script>
</body>
</html>