vue3使用工具类和自定义指令分别实现节流throttle和防抖debounce

使用工具类实现

1. 新建util.js

// 防抖
const mydebounce = (fn, delay, immediate = false) => {
	let timer = null
	let isInvoke = false
	const _debounce = function(...args) {
		if (timer) clearTimeout(timer)
		if (!isInvoke && immediate) {
			fn.call(this, args)
			isInvoke = true
			return
		}
		timer = setTimeout(() => {
			fn.call(this, args)
			timer = null
			isInvoke = false
		}, delay)
	}
	_debounce.cancel = function() {
		if (timer) clearTimeout(timer)
		timer = null
		isInvoke = false
	}
	return _debounce
}

// 节流
const myThrottle = (fn, interval, immediate = true) => {
	let startTime = 0
	const _throttle = function(...args) {
		const nowTime = new Date().getTime()
		if (!immediate && startTime === 0) {
			startTime = nowTime
		}
		const waitTime = interval - (nowTime - startTime)
		if (waitTime <= 0) {
			fn.apply(this, args)
			startTime = nowTime
		}
	}
	return _throttle
}

export default {
	mydebounce,
	myThrottle
}

2:页面内使用

示例:使用防抖处理resize监听

import util from '@/utils/util.js'
// 接收防抖函数
const cancalDebounce = util.mydebounce(initCanvas, 500)
// 页面卸载时去掉事件
onUnmounted(() => {
	window.removeEventListener('resize', cancalDebounce);
})
onMounted(() => {
	window.addEventListener('resize', cancalDebounce)
})

自定义指令实现

1:新建tools.js

export const toolsFunc = (app) => {
	/*
	 * @Descripttion: 防抖,单位时间内触发最后一次
	 * @param [function] func --执行事件
	 * @param [?number|300] wait = 300 -- 时间间隔
	 * @param [?string|"click"] event -- 事件类型
	 * @param [?boolean|true] boolean -- 事件冒泡-false , 事件捕获--true
	 * @param [Array] binding.value - [func,type,wait,true]  
	 * <a-button v-debounce="[func,'click',1000,true]">防抖测试</a-button>
	 */
	app.directive('debounce', {
		beforeMount(el, binding) {
			let [
				func,
				type = 'click',
				wait = 300,
				immediate = true
			] = binding.value;
			let timer = null
			el.$type = type;
			el.$handle = () => {
				timer && clearTimeout(timer)
				timer = setTimeout(() => func(), wait)
			}
			el.addEventListener(el.$type, el.$handle, immediate);
		},
		unmounted(el) {
			el.removeEventListener(el.$type, el.$handle);
		}
	})

	/*
	 * @Descripttion: 节流,单位时间内可触发一次
	 * @param [function] func --执行事件
	 * @param [?number|300] wait = 300 -- 时间间隔
	 * @param [?string|"click"] event -- 事件类型
	 * @param [?boolean|true] boolean -- 事件冒泡-false , 事件捕获--true
	 * @param [Array] binding.value - [func,type,wait,true]  
	 * <a-button v-throttle="[func,'click',1000,true]">防抖测试</a-button>
	 */
	app.directive('throttle', {
		beforeMount(el, binding) {
			let [
				func,
				type = 'click',
				wait = 300,
				immediate = true
			] = binding.value;
			let timer = null
			let timer_end = null
			el.$type = type;
			el.$handle = () => {
				if (timer) {
					clearTimeout(timer_end)
					return timer_end = setTimeout(func, wait)
				}
				func()
				timer = setTimeout(() => null, wait);
			}
			el.addEventListener(el.$type, el.$handle, immediate);
		},
		unmounted(el) {
			el.removeEventListener(el.$type, el.$handle);
		}
	})
}

2:添加全局导入

import { tools } from './directives/tools.js'
const app = createApp(App)
tools(app)

3:页面使用

已节流为例,onUp为click事件的名称,防抖事件使用方式相同

<img src="" class="yt_img yt_t" v-throttle="[onUp,'click', 10]" />
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值