【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);
};
    
相关推荐
sg_knight10 分钟前
拥抱未来:ECMAScript Modules (ESM) 深度解析
开发语言·前端·javascript·vue·ecmascript·web·esm
汝生淮南吾在北4 小时前
SpringBoot3+Vue3小区物业报修系统+微信小程序
微信小程序·小程序·vue·毕业设计·springboot·课程设计·毕设
苏打水com6 小时前
第十九篇:Day55-57 前端工程化进阶——从“手动低效”到“工程化高效”(对标职场“规模化”需求)
前端·css·vue·html
十月不到底6 小时前
vue3手机端列表加载组件
前端·vue
行走的陀螺仪8 小时前
前端基建从0到1搭建步骤清单(含工具选型+配置要点+落地注意事项)
前端·javascript·typescript·设计规范·前端工程化·规范化·前端基建
@AfeiyuO9 小时前
Vue3 热力图
vue·echarts
IT教程资源D11 小时前
[N_115]基于springboot,vue教务管理系统
mysql·vue·前后端分离·springboot教务系统
ttod_qzstudio12 小时前
Vue 3 的魔法:用 v-bind() 让 CSS 爱上 TypeScript 常量
css·vue.js·typescript
嘿siri12 小时前
uniapp enter回车键不触发消息发送,已解决
前端·前端框架·uni-app·vue
__万波__12 小时前
二十三种设计模式(十四)--命令模式
java·设计模式·命令模式