防抖和节流
使用场景
有时,我们会绑定一些持续触发的事件,如:resize、scroll、mousemove等,但是我们并不希望在事件持续触发的过程中那么频繁的去执行函数。通常情况下怎么去解决呢?一般来讲,防抖和节流是比较好的解决方案。
下面,我就已在vue中的input函数为例,讲解一下防抖和节流。
防抖
所谓防抖,就是指触发事件后在n秒内,函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行的时间。
其实防抖函数并不难写,下面这就是一个最初级的防抖函数:
<template>
<div id="app">
<el-input @input.native="inputFn" v-model='msg'></el-input>
</div>
</template>
<script>
export default {
components: {},
data(){
return{
msg: '',
timeout: ''
}
},
methods: {
// 最初级的防抖
inputFn(e){
if(this.timeout) clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
console.log('执行函数')
}, 3000)
}
}
}
</script>
接下来,我们利用闭包改造一下这个防抖函数,不要将timeout定义在函数外面了
<template>
<div id="app">
<el-input @input.native="inputFn" v-model='msg'></el-input>
</div>
</template>
<script>
export default {
components: {},
data(){
return{
msg: '',
timeout: '',
delay: ''
}
},
mounted(){
// 初始化防抖函数
this.delay = this.debounceFun(this.requestFun, 3000)
},
methods: {
inputFn(e){
this.delay('传入的参数')
},
// 第二版,非立即执行
// 非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
debounceFun(func, wait){
let timeout = ''
return function(){
let context = this
let args = arguments
if(timeout) clearTimeout(timeout)
timeout = setTimeout(() => {
func.apply(context, args)
}, wait)
}
},
requestFun(data){
console.log(data)
console.log('执行函数')
}
}
}
</script>
这样,我们就把防抖函数写好了,是不是很简单
这面的这种是非立即执行版的,下面我们再来改造一下,实现一版立即执行版的防抖函数
立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
// 第三版:立即执行 // 立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。 debounceFun(func, wait){ let timeout = '' return function(){ let context = this let args = arguments // 记录当前是否存在timeout,如果不存在,则说明是第一次 let isNow = !timeout if(timeout) clearTimeout(timeout) timeout = setTimeout(() => { func.apply(context, args) }, wait) // 如果不存在timeout,说明是第一次触发,则执行一次回调函数 if(isNow) func.apply(context, args) } }
下面,我们再来写一版立即执行和非立即执行的合并版
// 第四版 // 当immediate为true时,是立即执行版;当immediate为false时,是非立即执行版 debounceFun(func, wait, immediate){ let timeout = '' return function(){ let context = this let args = arguments // 记录当前是否存在timeout,如果不存在,则说明是第一次 let firstFlag = !timeout if(timeout) clearTimeout(timeout) timeout = setTimeout(() => { func.apply(context, args) }, wait) if(immediate){ // 如果不存在timeout,说明是第一次触发,则执行一次回调函数 firstFlag && func.apply(context, args) } } }
节流
所谓节流,就是指连续触发事件,但是在n秒钟只执行一次的函数。节流会稀释函数的执行频率
throttleFun(func, wait){ let timeout = '' return function(){ let context = this let args = arguments if(!timeout){ timeout = setTimeout(() => { timeout = null func.apply(context, args) }, wait) } } }

浙公网安备 33010602011771号