防抖的原理:事件响应函数在一段事件后才执行,如果这段时间内再次调用,则重新计算执行事件,当预定的时间内没有再次调用该函数,则调用时间响应函数(意思就是时间触发之间的间隔必须大于设置时间)
应用场景
- scroll事件滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交事件
- 浏览器窗口缩放、resize事件
debounce.js文件
/*
@function
debounce:鼠标在目标元素移动mousemove绑定的事件
(频繁的事件触发还有window的resize,scroll;mousedown,mousemove;keydown,keyup
getUserAction:改变数字的动作
@paras
count:记住触发的次数
timeout:每次mousemove都会产生的定时器
result:考虑getUserAction有返回值,只有再immediate为true才有返回值
immediate:立即执行功能(默认为false)
callNow:是否立即执行的标志
*/
function debounce(func, wait, immediate) {
var timeout;
var result;
var debounced = function () {
var context = this; // this-> container
var args = arguments;
if (timeout) clearTimeout(timeout);
// 立即执行,不需要等到事件停止触发后才执行,希望立即执行,然后等到n秒后可以重新触发执行
if (immediate) {
// 已经执行过的不再执行
var callNow = !timeout;
//等待n秒后可以重新触发
timeout = setTimeout(function () {
timeout = null;
}, wait);
// 立即执行
if (callNow) result = func.apply(context, args);
}
else {
// 不会立即执行,设置定时操作
timeout = setTimeout(function () { //这里使用箭头函数也可以实现this指向的改变
console.log(this);// -> window
func.apply(context, args); // -> container args传入鼠标事件对象MouseEvent
}, wait);//等待n秒后,执行func(),同时改变this指向
}
return result;
};
debounced.cancel = function () {
clearTimeout(timeout);
timeout = null; //防止内存泄漏
};
return debounced;
}
var count = 1;
var container = document.getElementById('container'); //获取container元素
var btn = document.getElementById('btn');
// 改变数字的动作
function getUserAction(e) {
// 可能做回调或者ajax请求(这样大量的无效的请求,对服务器是负担)
container.innerHTML = count++;
// event指向
console.log(e);
//改变执行函数内部的this
console.log(this);// -> container
}
var setUserAction = debounce(getUserAction, 1000);
// this->container
container.onmousemove = setUserAction;
btn.onclick = function () { setUserAction.cancel(); console.log("ok"); }
//取消功能只能在immediate为false下才有意义
html文件
<!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;
}
button {
display: block;
top: 20px;
left: 20px;
}
</style>
</head>
<body>
<div id="container"></div>
<button id="btn">取消</button>
<script src="debounce.js"></script>
</body>
</html>