前言
这是手写系列的第一篇文章,如有错误/好的写法欢迎大家在评论区交流~
防抖
应用场景
- 适合大量事件一次响应
- 适用于需要限制函数执行频率的场景,特别是在处理用户输入、页面滚动、窗口调整等频繁触发事件的情况下。
具体案例
- 如音乐平台在线搜索功能,在用户输入搜索关键字时会实时向服务器发送请求并展示搜索结果。为了减少不必要的请求和提升搜索体验,可以使用防抖技术。
思路
- 延迟函数执行并重新计时以确保在一段时间内只执行一次函数。
手写代码
html
<!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>
<div>
<span>正常情况:</span>
<input type="text" id="nondebounce">
</div>
<div>
<span>实现防抖时:</span>
<input type="text" id="debounce">
</div>
<script>
const nondebounceDom = document.getElementById('nondebounce')
// 正常情况下,每次键盘抬起都会触发 ajax 函数
nondebounceDom.addEventListener('keyup', function () {
ajax()
})
const debounceDom = document.getElementById('debounce')
// 使用防抖函数,确保在连续触发 keyup 事件时只触发一次 ajax 函数
debounceDom.addEventListener('keyup', debounce(ajax, 500))
// 模拟一个 ajax 请求
function ajax() {
console.log('这是一个请求');
}
// 实现防抖的函数
function debounce(fn, time) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
// 使用 apply 将函数 fn 的执行上下文设置为当前函数的执行上下文,并传入当前函数的参数
fn.apply(this, arguments)
}, time)
}
}
</script>
</body>
</html>
节流
应用场景
- 适合大量事件按固定时间平均触发
- 适用于需要控制事件触发频率的场景,特别是在处理高频率事件,如页面滚动、鼠标移动、键盘按键事件等情况下。
具体案例
- 假设有一个在线地图应用,在用户拖动地图时会触发地图移动事件,需要根据地图移动的位置实时更新附近的地点信息。为了减少地点信息更新的频率,可以使用节流技术。
思路
- 延迟函数执行,并确保在一定时间内只执行一次,以控制事件触发频率,提高性能和响应速度。
手写代码
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>
<div>
<span>正常情况:</span>
<input type="text" id="unThrottle">
</div>
<br>
<div>
<span>实现节流时:</span>
<input type="text" id="throttle">
</div>
</body>
<script>
// 获取未节流的输入框元素
const unDebounceDom = document.getElementById('unThrottle')
// 为未节流的输入框添加 keyup 事件监听器
unDebounceDom.addEventListener('keyup', function (e) {
// 模拟发送请求的函数,并传入输入框的值
ajax(e.target.value)
})
// 获取节流后的输入框元素
const debounceDom = document.getElementById('throttle')
// 使用节流函数包装发送请求的函数
debounceDom.addEventListener('keyup', function (e) {
throttleAjax(e.target.value)
})
// 模拟发送请求的函数
function ajax() {
console.log('这是一个请求');
}
// 使用节流函数节流发送请求的函数
let throttleAjax = throttle(ajax, 3000)
// 节流函数
function throttle(fn, time) {
let canRun = true
return function () {
if (!canRun) return
canRun = false
setTimeout(() => {
fn.apply(this, arguments)
canRun = true
}, time)
}
}
</script>
</html>