1、防抖
指触发事件后在n秒后函数执行,如果在n秒内又触发了事件,则会重新计算函数执行时间。应用场景(适合多次事件只响应一次的情况):给按钮加防抖函数防止表单多次提交;判断scroll是否滑到底部;对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
现给一个场景:现监听一个输入框,文字变化后触发change事件。若直接用keyup事件,则会频繁触发change事件。加了防抖后,用户输入结束或暂停时,才会触发change事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="input1">
</body>
<script>
const input1 = document.getElementById('input1')
//1、不加防抖 ,会一直触发change事件
input1.addEventListener('keyup', function(){
console.log(input1.value)
})
//2、简单实现防抖
let timer = null
input1.addEventListener('keyup', function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
//模拟触发change事件
console.log(input1.value)
//清空定时器
timer = null
}, 1000)
})
//3、将防抖函数这个工具进行封装
function debounce(fn, delay = 50){
//timer是闭包中的,不能被别人修改
let timer = null
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
input1.addEventListener('keyup', debounce(function(){
console.log(input1.value)
}, 600))
</script>
</html>
则封装后的防抖函数为:
function debounce(fn, delay = 50){
let timer = null //timer是闭包中的,不能被别人修改
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
2、节流
连续发送的事件在n秒内只执行一次函数。应用场景(适合大量事件按时间做平均分配触发):DOM元素拖拽;Canvas画笔功能。
现给一个场景:拖拽一个元素,要随时拿到该元素被拖拽的位置。若直接用drag事件,则会频繁触发,很容易导致卡顿。加了节流后,无论拖拽速度多快,都会每隔固定时间触发一次。
<!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>
#div1{
border: 1px solid #ccc;
width: 200px;
height: 100px;
}
</style>
</head>
<body>
<div id = "div1" draggable="true">可拖拽</div>
<script>
const div1 = document.getElementById('div1')
//1、简单实现节流
let timer = null
div1.addEventListener('drag', function(e){
if(timer){
return
}
timer = setTimeout(() => {
console.log(e.offsetX, e.offsetY)
timer = null //定时器执行了,才让timer为空
}, 1000)
})
//2、将节流函数这个工具进行封装
function throttle(fn, delay = 100){
let timer = null
return function(){
if(timer){
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
},delay)
}
}
div1.addEventListener('drag', throttle(function(e){ //形参e会传给throttle函数运行后返回的函数
console.log(e.offsetX, e.offsetY)
},200))
</script>
</body>
</html>
则封装后的节流函数为:
function throttle(fn, delay = 100){
let timer = null
return function(){
if(timer){
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
},delay)
}
}
网友评论