js - 防抖和节流
2021-11-28 本文已影响0人
梁庄十年
1 防抖 (debounce)
定义: 一段时间之后才执行某个函数; 实现方式主要是通过定时器; 防抖一般可以分为立即执行和后执行.
立即执行: 频繁触发事件, 第一次触发事件时会执行函数,后面触发如果在指定间隔时间内不会执行,过了间隔时间才会继续执行;
后执行: 频繁触发事件,事件只会在触发事件之后间隔定义的时间, 函数才会被执行, 而且只会执行最后一次触发的事件;
个人比较偏向立即执行, 下面的示例也是立即执行, 展示了局部使用和全局使用的方式;
- case1 : 直接在单个vue组件中定义的防抖函数
<template>
<div class="go-con">
<h1>debounce</h1>
<div class="chart-wrap">
<button @click="privateDebounce(testFunc, 1000, ['a', 'b'])">防抖</button>
</div>
</div>
</template>
<script>
export default {
name: 'debounce',
data () {
return {
timer : null,
}
},
methods: {
testFunc(params) {
console.log('debounce');
console.log(params);
},
handleResize() {
console.log('防抖');
},
// 自定义防抖函数
privateDebounce(func,wait = 500, ...args){
let nowTimer = !this.timer; // 是否立即执行
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = null;
}, wait)
if(nowTimer) {
func.apply(this,args)
}
}
}
}
</script>
- case2 定义成公共方法, 供全局使用
在main.js中, 将定义好的防抖函数, 挂载到 vue实例的原型上即可
function debounceFunc(func,wait = 500, ...args){
let nowTimer = !this.timer; // 是否立即执行
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = null;
}, wait)
if(nowTimer) {
func.apply(this,args)
}
}
Vue.prototype.$debounceFunc = debounceFunc;
在组件中使用
<template>
<div class="go-con">
<button @click="test">防抖 - 全局</button>
</div>
</template>
<script>
export default {
methods: {
test() {
this.$debounceFunc(this.testFunc, 1000, ['a', 'b', 'c'])
},
}
}
</script>
2 节流(throttle)
定义: 一段时间之内执行某个函数; 即在事件触发后,会先执行一次函数, 执行之后如果在指定的时间间隔内,用户再次触发该事件, 函数不会被执行,只有在超过了指定的时间间隔后才会再次被触发一次
- 用定时器的方式实现节流; 即等某段时间之后才执行, 并且在该段时间内不会重新计时;
<template>
<div class="go-con">
<button @click="throttle(getRandom, 1000)">节流</button>
</div>
</template>
<script>
export default {
name: 'throttle',
data () {
return {
timer : null,
}
},
methods: {
throttle(func, delay, ...args) {
if(this.timer) return; // 如果当前有计时, 直接return;
this.timer = setTimeout(() => {
func.apply(this, args);
this.timer = null; // 函数执行完, 要清除定时器, 否则无法进行下一次执行;
}, delay)
},
getRandom() {
console.log('throttle: ',Math.random());
},
},
}
</script>
- 用时间戳实现节流; 会立即执行, 下一次执行需要等待;
data () {
return {
prev: Date.now(),
}
},
methods: {
throttle(func, delay = 500, ...args) {
return (() => {
var now = Date.now();
if (now - this.prev >= delay) {
func.apply(this, args);
this.prev = Date.now();
}
})();
},
}