函数防抖
原理
触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。简单的说,当一个动作连续触发,则只执行最后一次
应用场景
- 搜索功能实现
- 手机号码验证和邮箱验证
- 窗口大小Resize,只需窗口调整完成后,计算窗口大小,防止重复渲染
1. 普通JS中使用
<body>
<input type="text" id="inp">
<script>
var timer = null
var input = document.getElementById("inp")
inp.oninput = function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
ajax()
}, 300)
}
function ajax() {
console.log('ajax发送的数据为: ' + input.value)
}
</script>
</body>
2. vue中使用
创建一个 common.js 文件
export default {
debounce(fn, delay = 300) { // 默认300毫秒
var timer
return function() {
var args = arguments
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args) // this 指向 vue
}, delay)
}
}
}
在 vue 文件中引入并使用
import { debounce } from './common'
export default {
methods: {
search: debounce(function() {
this.getData()
})
}
}
函数节流
原理
触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用
应用场景
- 高频点击提交,表单重复提交
- 上拉加载,加载更多或滚到底部监听
1. 定时器版
// 定时器版
<script>
var canRun = true
document.onscroll = function(){
if(!canRun){
// 判断是否已空闲,如果在执行中,则直接return
return
}
canRun = false
setTimeout(function(){
console.log("函数节流")
canRun = true
}, 300)
}
</script>
2. 时间戳版
// 时间戳版
<script>
let startTime = Date.now() // 开始时间
let time = 500 // 间隔时间
let timer
window.onscroll = function throttle(){
let currentTime = Date.now()
if(currentTime - startTime >= time){
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop
console.log('滚动条位置:' + scrollTop)
startTime = currentTime
}else{
clearTimeout(timer)
timer = setTimeout(function () {
throttle()
}, 50)
}
}
</script>
函数防抖和函数节流的区别
相同点
- 都可以通过使用 setTimeout 实现
- 降低回调执行频率,节省计算资源
不同点
- 函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
- 函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次