本文已同步到:个人博客
函数的防抖
定义
函数防抖:当持续触发事件是,一定事件内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。此技术多用于文本搜索框搜索信息展示功能等情况
上面定义有点抽象,打个比方,比如我准备连续搞7天学习,结果我只搞了三天学习,第四天晚上打游戏去了没搞学习,结果我又立下了一个flag,重新开始连续搞七天学习。
代码
下面代码模拟一个场景:监听一个输入框文字变化后触发的change事件,直接用keyup事件,则会频繁触发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>
<style>
input{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
border: solid 2px ;
/* border-radius: 50%; */
height: 50px;
width: 500px;
}
</style>
</head>
<body>
<input type="text" />
</body>
<script>
const inp = document.querySelector('input')
// inp.onkeyup = function () {
// console.log(inp.value);
// }
function debounced(fn, delay=500) {
let timer = null
return function () {
if (timer) {
clearInterval(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
inp.addEventListener('keyup',debounced(()=>{
console.log(inp.value);
},1000))
</script>
</html>
应用场景
- search搜索联想,用户在不断的输入值时,用防抖来节约请求资源
- window触发resize的时候
- 不断的调整浏览器窗口大小会不断的触发这个事件,用防抖只会让其只触发一次
- 放置重复提交
函数的节流
定义
控制方法的执行周期,减少一些无用的请求,优化性能
应用场景
- 鼠标不断的点击触发mousedown(单位时间只触发一次)
- 监听滚动事件,比如石佛那个滑到底部自动加载更多。
代码
下面代码将模拟一个应用场景:拖拽一个元素是,要随时获取元素被拖拽的位置,直接用drag事件则会频繁触发,很容易导致卡顿,现在将使用节流:无论拖拽速度多块,都会每隔限定的一段周期触发一次<.font>
<!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>
.box {
width: 100px;
height: 100px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
/* top: 50%;
left:50%;
transform: translate(-50%,-50%); */
border: solid 2px yellowgreen;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box" draggable="true"></div>
</body>
<script>
const box = document.querySelector('.box')
console.log(box);
function throttle(fn, interval=500) {
let timer = null
// 注意:这其实是一个闭包
return function () {
if (timer) {
return //因为和防抖不同,不需要重新开始计时,所以不用清楚timer
}
timer = setTimeout(()=>{
fn.apply(this,arguments)
timer = null
},interval)
}
}
box.addEventListener('drag',throttle(function(e){
console.log(e.offsetX,e.offsetY);
}))
</script>
</html>