【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);
};
    
相关推荐
Amore05256 小时前
React+TS前台项目实战(二十三)-- 基于属性自定义数值显示组件Decimal封装
前端·react.js·typescript·前端框架
小C学安全7 小时前
【VUE基础】VUE3第三节—核心语法之ref标签、props
前端·vue.js·typescript
Mrceel8 小时前
java spring boot 单/多文件上传/下载
java·spring boot·vue
xinZhu810 小时前
Vue3+.NET6前后端分离式管理后台实战(二十七)
前端·vue.js·typescript·vue·asp.net
多多睡觉1112 小时前
Cookie的默认存储路径以及后端如何设置
java·spring·vue
valsedefleurs12 小时前
前端FCP指标优化
前端·javascript·vue
Hello World呀19 小时前
DataV大屏组件库
vue.js·vue·大屏端
Hello攻城狮21 小时前
qiankun实现子应用tab页签切换缓存页面
前端·缓存·vue
程序员储物箱1 天前
Vue报错:Module not found: Error: Can‘t resolve ‘less-loader‘ in ‘文件地址‘
前端·vue
BestArsenaI1 天前
关于vue创建项目失败报错(镜像过期)的解决方案
npm·vue