【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);
};
    
相关推荐
zheshiyangyang3 小时前
TypeScript学习【一】
javascript·学习·typescript
子兮曰9 小时前
⭐告别any类型!TypeScript从零到精通的20个实战技巧,让你的代码质量提升300%
前端·javascript·typescript
摇滚侠9 小时前
Vue3入门到实战,最新版vue3+TypeScript前端开发教程,笔记02
vue
吴楷鹏9 小时前
TypeScript 为什么要增加一个 satisfies?
前端·typescript
zhong liu bin9 小时前
Vue框架技术详解——项目驱动概念理解【前端】【Vue】
前端·javascript·vue.js·vscode·vue
zhangzuying102610 小时前
基于Vue3 +ElementuiPlus + Dexie.js自研的浏览器插件新建标签页tab
vue.js·typescript·echarts
知识分享小能手10 小时前
React学习教程,从入门到精通,React 使用属性(Props)创建组件语法知识点与案例详解(15)
前端·javascript·vue.js·学习·react.js·前端框架·vue
知识分享小能手16 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
赵得C20 小时前
【前端技巧】Element Table 列标题如何优雅添加 Tooltip 提示?
前端·elementui·vue·table组件