在前端开发中经常会碰到一些频繁的事件触发,例如:
mouseover
keydown
resize
scroll
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
.container{
width: 500px;
height: 500px;
background: rgba(200, 20, 20, 0.3);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.container:hover{
background: rgba(200, 20, 20, 0.5);
}
style>
<title>Documenttitle>
head>
<body>
<div class="container">div>
<script>
let div = document.getElementsByClassName('container')[0];
div.addEventListener('mousemove', function(e){
console.log(e);
});
script>
body>
html>
如果只是像上面那样把事件对象输出还好,浏览器还应付得过来,如果是触发网络请求或者是其它消耗性能的操作就会导致卡顿的出现。
所以,为了避免事件频发触发而导致浏览器卡顿,一般有两种解决方法:
节流的原理就是,尽管是持续的触发事件,但也还是每个一段时间执行一次事件,从而避免了短时间执行大量的事件而造成的卡顿。
为了达到这个效果,可以使用定时器来实现。具体思路就是在事件第一次触发时会设置一个定时器,之后再次触发事件,除非上次设置的定时器执行完毕,否则不再设置定时器。这样,在一段时间内只会存在一个定时器,也就只有一个事件回调会被执行。
根据思路可以很容易写出代码
function throttle(func, wait){
let timerID = null;
return function(e){
let that = this;
if(timerID === null){
timerID = setTimeout(function(){
timerID = null;
func.call(that, e);
}, wait)
}
}
}
throttle
函数接受两个参数,第一个参数是**事件回调函数,也就是当事件发生后想要执行的操作。**第二个参数是事件,单位为毫秒,即为“希望多久触发一次事件”。
具体使用如下:
function throttle(func, wait){
let timerID = null;
return function(e){
let that = this;
if(timerID === null){
timerID = setTimeout(function(){
timerID = null;
func.call(that, e);
}, wait)
}
}
}
let test = throttle(function(e){
console.log(e);
}, 1000)
let div = document.getElementsByClassName('container')[0];
div.addEventListener('mousemove', function(e){
test(e);
});
防抖相对于节流来说更近一步,节流是无论怎样连续触发,结果都是每隔一段时间执行一次事件回调。而防抖,则更进一步。防抖是无论怎样连续触发,结果都是在事件触发结束一段时间之后执行事件回调。
防抖同样可以用计时器来实现,只要每次触发事件都清除一次计时器然后重新计时即可。
function debounce(func, wait){
let timerID = null;
return function(e){
let that = this;
clearTimeout(timerID);
timerID = setTimeout(function(){
func.call(that, e);
}, wait);
}
}
具体使用如下:
function debounce(func, wait){
let timerID = null;
return function(e){
let that = this;
clearTimeout(timerID);
timerID = setTimeout(function(){
func.call(that, e);
}, wait);
}
}
let test = debounce(function(e){
console.log(e);
}, 1000)
let div = document.getElementsByClassName('container')[0];
div.addEventListener('mousemove', function(e){
test(e);
});
效果如下:
节流和防抖是防止事件频繁触发而导致卡顿的两种解决方案。节流是每隔一段时间执行一次事件回调,而防抖则是在事件停止触发一段时间以后执行一次事件回调。具体选择哪种方法还是得看实际需求。