一、实现防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
比如说一个倒计时按钮,倒计时10秒,过了两秒,有人再次触发按钮,又要重新计时,再等10秒。
实现防抖思路:通过闭包维护一个变量,此变量代表是否已经开始计时,如果已经开始计时则清空之前计时器,重新计时。
<script>
// 首先闭包里面要有一个变量,这个变量是个计时器,
// 我们要判断这个计时器是否已经计时了,如果已经
// 计时了我们就把原先的清空掉
// 不管有没有计时器,我们设置一个计时器,然后把函数和时间传进来
// 传进来的函数有参数,还有this指向,用arguments和apply
function debounce(fn, time) {
let timer = null;
return function() {
let args = arguments;
let context = this;
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function() {
fn.apply(context, args);
}, time);
};
}
function test(num) {
console.log(num);
console.log(this);
}
let newFn = debounce(test, 1000);
window.onscroll = function() {
newFn(123);
};
</script>
// 这个案例就是展示搜索框内容提示,为避免不必要的请求,设置一个定时器,
// 800 毫秒向服务器发送一次请求,如果期间文本框值发生变化,则清空计时器,不发送请求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>搜索框输入文字自动提示</title>
<link
rel="stylesheet"
href="//www.greatytc.com/assets/bootstrap/dist/css/bootstrap.min.css"
/>
<style type="text/css">
.container {
padding-top: 150px;
}
.list-group {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="form-group">
<input
type="text"
class="form-control"
placeholder="请输入搜索关键字"
id="search"
/>
<ul class="list-group" id="list-box"></ul>
</div>
</div>
<script src="/js/ajax.js"></script>
<script src="/js/template-web.js"></script>
<script type="text/html" id="tpl">
{{each data}}
<li class="list-group-item">{{$value}}</li>
{{/each}}
</script>
<script>
// 获取搜索框
var searchInp = document.getElementById("search");
// 获取提示文字的存放容器
var listBox = document.getElementById("list-box");
// 存储定时器的变量
var timer = null;
searchInp.oninput = function() {
clearTimeout(timer);
var key = this.value;
if (key.trim().length == 0) {
listBox.style.display = "none";
return;
}
timer = setTimeout(function() {
ajax({
type: "get",
url: "http://localhost:3000/searchAutoPrompt",
data: {
key: key
},
success: function(data) {
var html = template("tpl", { data: data });
console.log(data);
listBox.innerHTML = html;
listBox.style.display = "block";
}
});
}, 600);
};
</script>
</body>
</html>
二、实现节流:在一段时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被多次触发,只能有一次生效。
例如发送验证码倒计时按钮,必须等够多少秒后才可以再次发送。
实现思路:通过闭包维护一个变量,次变量代表是否允许执行函数,如果允许则执行函数并且把该变量修改为不允许,并使用定时器在规定时间后恢复变量。
<script>
function throttle(fn, time) {
let canRun = true; //是否允许fn 函数被执行
return function() {
if (canRun) {
fn.apply(this, arguments);
canRun = false;
setTimeout(function() {
canRun = true;
}, time);
}
};
}
function test(num) {
console.log(num);
console.log(this.age);
}
let obj = {
age: 18
};
let newFn = throttle(test, 2000);
obj.newFn = newFn;
window.onscroll = function() {
obj.newFn("123");
};
</script>