本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
今天来谈一谈JS中的函数防抖和函数节流,浅浅的剖析一下其中的一些门道。在实际项目中也会遇到一些应用场景需要使用到防抖和节流,包括在面试中也算是高频出现了,今天就与大家一同来学习一下。
函数防抖
概念
触发事件后不是立即执行回调,而是设定一段时间后再执行回调,若在回调触发之前再次触发事件,则重新计时。 简言之,避免一段时间内太过频繁的触发事件回调(如输入框的input事件),尽量减少用户触发事件回调的次数,减少性能损耗。
例子
这里使用vue的写法来模拟一个input框实现函数防抖。
<template>
<el-input v-model="test" @input="debounce"/>
</template>
<script>
export default {
data() {
return {
test: undefined,
timer: undefined
}
},
methods: {
debounce() {
if(this.timer) { // 清除定时器
clearTimeout(this.timer)
}
timer = setTimeout(() => {
// 具体业务实现
console.log(this.test)
},1000)
}
}
}
</script>
思路就是用一个定时器来控制事件回调中具体业务的延迟触发,若在设定的时间内再次触发事件回调,则清除定时器,重新再设置定时器,这样就可以有效的减少业务触发的次数。
函数节流
概念
设定一段时间内只触发一次事件回调,也就是n毫秒内不管触发多少次事件,都只执行一次回调。
例子
同样的用vue的写法来模拟input框实现函数节流。
<template>
<el-input v-model="test" @input="debounce"/>
</template>
<script>
export default {
data() {
return {
test: undefined,
open: true
}
},
methods: {
throttle() {
if(this.open) {
setTimeout(() => {
// 具体业务实现
console.log(this.test)
this.open = true
},1000)
}
this.open = false
}
}
}
</script>
原理其实也蛮简单的,就是类似于设定一个开关来控制定时器的运转,在你设置的间隔之内限制住了开关,在特定时间内就只能触发一次,这是利用定时器方法来实现函数节流,其实还有一种方法是使用时间戳方案来实现函数节流的做法,也来举例一下。
<template>
<el-input v-model="test" @input="debounce"/>
</template>
<script>
export default {
data() {
return {
test: undefined,
open: true
}
},
methods: {
throttle() {
let now = Date.now()
if(now - this.open >= 1000){
console.log(this.test)
this.open = Date.now()
}
}
}
}
</script>
这样也能实现函数节流的效果,原理就是判定是否超过所设定的时间间隔,若超过,则执行业务操作,若未超过,那就直接跳出函数。具体选用哪种方法就看大家自己的喜好了。
浅谈应用场景
函数防抖:在很多系统触发用户搜索的时候可以使用,最好是能确保用户填写完毕之后再请求数据,使用防抖来减少请求。当然还有其它很多地方可以使用,目前写文的时候就暂时想到了这个,大家可以灵活变通按照实际项目情况来使用。
函数节流:监听滚动事件时,一个比较常见的应用场景,滚动下拉加载数据。还有监听一些拖拽操作的同时也可以应用,具体还是要按照实际需求使用来分析。
总结
上面的代码只是简单实现了函数防抖和节流的功能,想做的更好一些也可以封装成工具函数来使用,两种方法都是为了优化程序性能,提升用户体验,在合适的时候使用这两种优化方案才能达到对应的效果。例如有些要求就是要让用户实时得到反馈,这时候用上节流和防抖就显得不太合适了,在用户体验和性能优化的选择上,总是要做一些取舍的,切勿滥用,按照实际情况来决定是否选用才好。
最后感谢各位看官能看到这里~