应用:
在我们开发过程中,会有一些用户操作,如滚动事件,输入事件等导致一直重复调用某函数,频率无限,使浏览器负担过重,导致页面卡顿。这时候就会用到防抖和节流来控制调用频率,减少浏览器负担。
区别:
防抖:设置一个时间段A来做延时,在事件触发后A时间段内没有再次触发事件,那么函数会在A时间段过后自动执行一次;如果在还没到达A时间段,再次触发事件,那么会根据最后一次触发来重新计算A时间段,延时执行;如下图:
节流:设置一个时间段B,在事件触发后,B时间后再次执行,不管用户触发多少遍事件,函数只会每隔B段时间执行一次;
综上所述:防抖就是将无限次数变为最后一次执行,节流是将无限次数变为每隔一段时间执行;
实现:
防抖(debounce):防抖分为非立即执行与立即执行,非立即执行为触发后过一段时间才执行函数;立即执行为触发后马上执行函数,然后等待规定时间过后,再次触发有效,再次立即执行;
非立即执行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加入防抖</title>
<style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
</style>
</head>
<body>
<div>
加入防抖后的输入:非立即执行
<input type="text" name="debounce" id="debounce">
<div id='box'>
在此移动
</div>
</div>
<script type="text/javascript">
// 防抖
//非立即执行
var i=0;
function debounce(fn, wait) {
console.log("执行")
var timeout ;
return function(){
if(timeout!== null) {
clearTimeout(timeout)
}
timeout = setTimeout(fn,wait);
}
}
// 处理函数
function handle() {
i++;
console.log(i+"次执行")
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
</script>
</body>
</html>
立即执行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加入防抖</title>
<style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
</style>
</head>
<body>
<div>
加入防抖后的输入:立即执行
<input type="text" name="debounce" id="debounce">
<div id='box'>
在此移动
</div>
</div>
<script type="text/javascript">
// 防抖
//立即执行
var i=0;
function debounce(fn, wait) {
var timeout ;
return function(){
if(timeout!== null) {
clearTimeout(timeout)
}
var flag=!timeout;
timeout = setTimeout(function(){
timeout=null;
},wait);
if(flag){
handle()
}
}
}
// 处理函数
function handle() {
i++;
console.log(i+"次执行")
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
</script>
</body>
</html>
节流(throttle):实现函数节流也有两种办法:时间戳和定时器;
时间戳方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加入防抖</title>
<style type="text/css">
#box{
width:500px;
height: 500px;
background: red;
}
</style>
</head>
<body>
<div>
加入节流后的输入:时间戳
<input type="text" name="debounce" id="inp">
<div id='box'>
在此移动
</div>
</div>
<script type="text/javascript">
//节流
var i=0;
var throttle = function(fn, way) {
var prev = Date.now();
return function() {
var now = Date.now();
if (now - prev >= way) {
handle();
prev = Date.now();
}
}
}
function handle() {
i++;
console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
</script>
</body>
</html>
定时器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加入防抖</title>
<style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
</style>
</head>
<body>
<div>
加入节流后的输入:定时器
<input type="text" name="debounce" id="inp">
<div id='box'>
在此移动
</div>
</div>
<script type="text/javascript">
// 节流
var i=0;
var throttle = function(fn, way) {
var timer = null;
return function() {
if (!timer) {
timer = setTimeout(function(){
handle()
timer=null;
}, way);
}
}
}
function handle() {
i++;
console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
box.onmousemove=throttle(handle, 2000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 2000);
</script>
</body>
</html>
以上两种方式,都各有弊端,时间戳在最后一次触发后不执行函数,而定时器是第一次触发的时候没有立即执行函数,这两种方式无法完美的满足需求,所以我们优化了一下节流方式,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>加入防抖</title>
<style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
</style>
</head>
<body>
<div>
加入节流后的输入:定时器
<input type="text" name="debounce" id="inp">
<div id='box'>
在此移动
</div>
</div>
<script type="text/javascript">
// 节流
var i=0;
var throttle = function(fn, way) {
console.log(11)
var timer = null;
var startTime = Date.now();
return function() {
var nowTime = Date.now();
var remaining = way - (nowTime - startTime); //剩余时间
clearTimeout(timer);
if (remaining <= 0) { // 第一次触发立即执行
handle();
startTime = Date.now();
} else {
timer = setTimeout(function(){
i++;
console.log(i+"次数");
startTime = Date.now();
}, remaining); //取消当前计数器并计算新的remaining
}
}
}
function handle() {
i++;
console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
</script>
</body>
</html>
时间戳+定时器版如有优化建议,欢迎提出!跪谢!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。