【VUE3】自定义防抖指令

目前在使用Vue3+TypeScript开发前端项目。时长遇到"手抖"选手,导致多次请求等问题。

Vue 3 允许你创建自定义指令,以便在 DOM 上应用一些特殊的行为。自定义指令具有几个可用的钩子函数,如 bind、inserted、update、componentUpdated 和 unbind,它们会在指令的不同生命周期阶段被调用。

下面是如何在 Vue 3 中创建一个自定义指令的基本步骤:

定义自定义指令

你可以在组件内部定义指令,也可以全局定义它们。

局部定义(在组件内部):

javascript 复制代码
export default {
  directives: {
    focus: {
      // 当被绑定的元素插入到 DOM 中时调用
      inserted: function (el) {
        el.focus()
      }
    }
  }
}

全局定义

javascript 复制代码
const app = Vue.createApp({})

app.directive('focus', {
  inserted: function (el) {
    el.focus()
  }
})

使用自定义指令

在你的模板中,你可以像使用内置指令一样使用自定义指令:

html 复制代码
<template>
  <input v-focus>
</template>

使用钩子函数

除了 inserted,你还可以使用其他钩子函数,如 bind、update、componentUpdated 和 unbind。

例如,下面的指令会在元素的值更新时改变其颜色:

javascript 复制代码
app.directive('color-on-update', {
  bind(el, binding, vnode) {
    el.style.color = 'black'
  },
  update(el, binding, vnode, prevVnode) {
    el.style.color = 'red'
  }
})

然后,你可以在模板中这样使用它:

html 复制代码
<template>
  <p v-color-on-update="someReactiveProperty">This text will turn red when `someReactiveProperty` changes.</p>
</template>

传递参数给自定义指令

你可以通过指令的值、修饰符或表达式传递参数给自定义指令。例如:

html 复制代码
<template>
  <p v-highlight="'yellow'">Highlighted text</p>
</template>

在自定义指令中,你可以通过 binding.value 访问这个值:

javascript 复制代码
app.directive('highlight', {
  bind(el, binding) {
    el.style.backgroundColor = binding.value
  }
})

动态指令参数

Vue 3 还支持动态指令参数,这意味着你可以根据组件的状态动态地改变指令的行为。例如:

html 复制代码
<template>
  <p v-highlight:[dynamicColor]>Dynamically highlighted text</p>
</template>

<script>
export default {
  data() {
    return {
      dynamicColor: 'blue'
    }
  }
}
</script>

在自定义指令中,你可以这样处理动态参数:

javascript 复制代码
app.directive('highlight', {
  bind(el, binding) {
    const color = binding.arg || 'defaultColor' // 如果动态参数不存在,则使用默认值
    el.style.backgroundColor = color
  }
})

通过这些方法,我们来创建一个防抖指令

typescript 复制代码
// 定义防止重复点击的指令
export const preventReClick = {
    created(el:any, binding:any, vnode:any, prevVnode:any) {
        console.log(vnode,prevVnode);
        
        el.addEventListener('click', (e:any)=>customClick(e,binding,el));
    },
    // 离开一定要销毁卸载
    unmounted(el:any, binding:any, vnode:any) {
        console.log(binding,vnode);
        
        el.removeEventListener('click', customClick);
    },
};
// 逻辑封装
const customClick = (e:any,binding:any,el:any) => {
//阻止事件冒泡
    e.stopPropagation()
        if (!el.disabled) { // 判断条件
            el.disabled = true
            setTimeout(() => {
                el.disabled = false
            },binding.arg||1000)
            // 正常触发点击事件
            binding.value();
        } else {
            // 已经成功拦截点击事件
            console.log('已经成功拦截点击事件');
        };
    
};
//指令抛出
export const setupAuthDirective = (app:any) => {
  app.directive('click', preventReClick);
};
    
相关推荐
ox00805 小时前
C++ 设计模式-命令模式
c++·设计模式·命令模式
Pro_er6 小时前
Vue3 数据响应式原理与高效数据操作全解析
vue·前端开发
寰宇软件10 小时前
PHP培训机构教务管理系统小程序源码
小程序·uni-app·vue·php
IT、木易11 小时前
TypeScript跟js,es6这些的区别
javascript·typescript·es6
暗星涌动11 小时前
Java 与设计模式(16):命令模式
java·设计模式·命令模式
咖啡不加糖�15 小时前
base64转文件流上传给后端
前端·javascript·vue
李二。19 小时前
TypeScript学习:初学
typescript
Smile_Gently1 天前
前端:最简单封装nmp插件(组件)过程。
前端·javascript·vue.js·elementui·vue
ThomasChan1231 天前
vue3.x 的 toRef详细解读
前端·javascript·vue.js·node.js·vue·bootstrap·less