因为项目中很多按钮都需要做防抖处理 所以就学习了下v-directive的实现。废话不多说直接贴代码了
// utils/index.js
// 防抖函数 immediate: true 立即执行-前沿触发 false 为非立即触发-后沿触发
export const debounce = (fn, delay = 1000, immediate = true) => {
let timer = null
return function() {
if(timer) {
clearTimeout(timer)
}
let now = immediate && !timer
timer = setTimeout(()=>{
timer = null
!immediate? fn.call(this) : null
}, delay)
now ? fn.call(this) : null
}
}
然后创建directive文件夹存放 自定义指令
// directive/index.js
import Vue from "vue";
import { debounce } from '@/utils'
// 注:此为vue2.0+版本 vue3 生命周期钩子改变 beforeMount
Vue.directive("debounce", {
bind(el, binding) {
let val = binding.value, // 获取指令传递的参数
wait = 500 , // delay默认500
immediate = false,
type = 'click',
params = [],
func
if(val == null) return //如果没有传递任何参数则什么也不做
if(typeof val !== 'object' && typeof val !== 'function') return //如何传递的参数既不是对象也不是函数则也什么都不做
if(binding.arg) {
wait = +binding.arg // 获取冒号后的参数
}
if(binding.modifiers && binding.modifiers.immediate) {
immediate = binding.modifiers.immediate
}
if(typeof val === 'function') func = val;//如果传递的是函数则直接赋给func
// 如果是对象则对对象进行解析
if(typeof val === 'object') {
func = val.func || function(){};
type = val.type || 'click';
params = val.params || [];
}
el.$type = type;
el.$handle = debounce(function(...args){
return func.call(this, ...params.concat(args))
}, wait, immediate)
el.addEventListener(el.$type, el.$handle)
},
unbind(el) {
el.removeEventListener(el.$type, el.$handle);
}
});
使用方法
<template>
<div class="vdirect">
vue 自定义指令
<!-- 需要传参类型 还有[]动态传参 有兴趣的小伙伴可以查看vue官方实现-->
<button v-debounce:[wait].immediate="()=>demoFn(item)">防抖</button>
<!-- 直接调用 -->
<button v-debounce="demoFn">防抖</button>
</div>
</template>
export default {
name: 'App',
data() {
return {
item: {
key: 'hello',
},
wait: 3000
}
},
methods: {
demoFn(item) {
console.log(item.key); // hello 传参版
},
}
}