防抖节流的相同与不同
防抖
定义:
触发事件后,函数在n秒内只执行一次,如果事件再次触发,则会重新计算函数执行时间
实际应用:
(1) input输入框频繁输入,进行模糊查找。在最后一次键盘抬起后的一秒,进行数据请求
节流
定义:连续触发的事件中,函数只在n秒内执行一次
实际应用:
(1) 点击按钮请求数据请求,如果频繁点击,对于网络不好,或者返回数据慢的情况。会造成页面数据混乱,那我们规定在n秒内只执行一次,就能很好的稀释这个频繁请求
(2) 浏览器的scroll()滚动事件,在图片赖加载的时候,我们需要监听浏览器的滚动位置,来加载图片。这个时候可以用节流,来稀释监听的频率,哪怕是100毫秒,也是很大的优化了。无论加载多块,都有时间差。
(3) 浏览器的onresize()缩放,在pc适配移动端时,如果需要频繁监听浏览器的缩放,来判断当前页面展示是pc还是移动端。
概念使用总结
- 节流和防抖,都是解决频繁性事件的回调,造成页面性能消耗,卡顿
- (如果不设置立即执行)防抖是只在最后最后一次事件执行时触发
- (如果不设置立即执行)节流是在稀释了执行频率,在连续触发的事件中,函数在n秒只执行一次
防抖函数实现
普通版
实现输入框防抖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input id="getId" />
</body>
<script>
let id = document.getElementById('getId')
function debounce(callBack, delay) {
let timeout // 这里使用闭包。在当前事件执行完毕之后,在下次事件执行时,依然保存上一次变量的状态
return function (value) {
console.log('参数', value)
if (timeout) clearTimeout(timeout) // 每次事件触发,都要清空定时器,重新计算下次执行时间
timeout = setTimeout(() => {
callBack(value) // 外部输出结果,所以用了个回调函数
}, delay)
}
}
function getData(e) {
console.log('一秒后输出', e)
}
let debounceFunc = debounce(getData, 1000)
id.addEventListener('keyup', function (e) {
debounceFunc(e.target.value)
})
</script>
</html>
节流实现
时间戳和定时器版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">节流</button>
</body>
<script>
let btn = document.getElementById('btn')
// 时间戳版(立即执行)
// function throttle(func, wait) {
// let prev = 0
// return function () {
// let now = new Date
// if (now - prev > wait) {
// // 立即执行
// func()
// prev = now
// }
// }
// }
// 定时器版(等到wait之后执行)
function throttle(func, wait) {
let timeout
return function () {
if (!timeout) // 如果定时器存在,就不执行
{
timeout = setTimeout(() => {
func()
timeout = null // 执行完毕,记得清空,方便下一次定时器判断
}, wait);
}
}
}
// 如果我想第一次延迟wait执行,最后一个如果没有wait了,那我立即执行
// function throttle(fn, wait) {
// let timeout = null
// let prev = 0
// return function () {
// let now = Date.now()
// let remaiing = wait - (now - prev)
// if (remaiing <= 0) {
// fn.apply(this, arguments)
// } else {
// timeout = setTimeout(() => {
// fn.apply(this, arguments)
// }, remaiing)
// }
// }
// }
function func() {
console.log('doSomething')
}
btn.onclick = throttle(func, 1000)
</script>
</html>
后续文章输出
- 案例版图片赖加载实现(节流应用)
- onresize,输出文章。带移动端适配(节流应用)
- 改变this指向实现call,apply,bind(js知识点)