Vue中应用防抖与节流
防抖
在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。
通常这种情况下我们怎么去解决的呢?一般来讲,防抖和节流是比较好的解决方案。
防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
使用场景:频繁触发、输入框搜索
因为防抖的特性,一直执行最后一次的触发,所以可以用于鼠标移动确定最后一次移动的时候的坐标位置。
export const Debounce = (fn, t) => {
let delay = t || 500;
let timer;
return function () {
let args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, delay);
};
};
应用一
注意使用时要先引入后再使用。
<template>
<div>
<input type='text' v-model='value' @keydown = "hangleChange">
</div>
</template>
<script>
export default{
name:'',
data(){
return{
value:''
}
},
methods:{
hangleChange:debounce(function(e){
console.log(this.value)
})
}
}
</script>
注意,在方法上可以hangleChange:debounce(()=> {})传入函数直接调用。
比如在页面滚动事件上添加防抖
_scrolling() {
// 一直监听,当停滞300ms时候触发
window.addEventListener(
'scroll',
debounce(() => {
this.onScrolling();
}, 300)
);
},
onScrolling() {
// 当到浏览器底部时候 向外抛出到底的事件
let rect = this.$refs.waiting.getBoundingClientRect();
if (!rect ||
rect.top - SCREEN_HEIGHT > 0
) {
return;
}
this.$emit(EVENT_BOTTOM);
}
节流
节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率(《JS高级程序设计第三版P614》)
使用场景:频繁触发、onrize,onscroll滚动条
因为节流是监听到第一次触发事件后就执行,所以可以用来防止按钮多次点击执行多次,且按照第一次点击的事件为准。
export const Throttle = (fn, t) => {
let last;
let timer;
let interval = t || 500;
return function () {
let args = arguments;
let now = +new Date();
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(() => {
last = now;
fn.apply(this, args);
}, interval);
} else {
last = now;
fn.apply(this, args);
}
};
};
应用一
<template>
<div class="scroll" ref="previewText" @scroll.passive="fnScroll">
</template>
<script>
export default{
name:'globalHospot',
data(){
return{
count:0,
fnScroll:() =>{}
}
},
methods: {
fnHandleScroll (e) {
console.log('scroll触发了:' + this.count++, new Date())
},
fnThrottle(fn, delay, atleast){ //节流函数
let timer = null;
let previous = null;
return function(){
let now = +new Date()
if(!previous) previous = now;
if(atleast && now - previous > atleast){
fn();
previous = now;
clearTimeout(timer)
}else{
clearTimeout(timer)
timer = setTimeout(()=>{
fn();
previous = null
},delay)
}
}
}
},
created(){
this.fnScroll = this.fnThrottle(this.fnHandleScroll, 1000) //刚创建时执行
},
}
</script>