vue3 实现自定义指令封装 --- 通俗易懂

1、局部自定义指令

1.1 在<script setup>定义组件内的指令,任何以v开头的驼峰式命名的变量都可以被用作一个自定义指令

javascript 复制代码
<template>
  <div>
    <h3>使用自定义指令</h3>
    <div>########################## start 局部自定义指令</div>
    <div>
        我是一个input:
        <input type="text" v-myFocus />
    </div>
    <div>########################## end 局部自定义指令</div>

  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
/**
 * 1、局部自定义指令, 在模板中启用 v-focus
 *    在<script setup>定义组件内的指令,任何以v开头的驼峰式命名的变量都可以被用作一个自定义指令
 *  为了区分下面全局自定义指令 v-focus,这里全局改为v-MyFocus
 */
// const vFocus = {
//     mounted: (el) => el.focus()
// }
const vMyFocus = {
    mounted: (el) => el.focus()
}
</script>

效果:

1.2 如果是vue3的options api, 自定义指令需要在directives选项中注册

javascript 复制代码
<template>
  <input v-focus />
</template>
<script>
export default{
  setup() {},
  directives: {
    // 指令名
    focus: {
      // 生命周期
      mounted(el) {
        // 处理DOM的逻辑
        el.focus()
      },
    }
  }
}
</script>

效果:

2、全局自定义指令

2.1 创建文件: src/directives/focus.js

javascript 复制代码
export default function(app) {
    app.directive('focus', {
        mounted(el) {
            console.log('focus指令, mounted')
            el.focus()
        },
    })
}

2.2 创建文件: src/directives/index.js

javascript 复制代码
import registerFocus from './focus'     // 获取焦点

export default function registerDirectives(app) {
    registerFocus(app)
}

2.3 main.js中引入

javascript 复制代码
import registerDirectives from './directives/index'

const app = createApp(App)
registerDirectives(app)

报警告如下:

index.vue:9 [Vue warn]: Failed to resolve directive: focus

at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > >

at <RouterView>

at <App>

2.4 页面内使用

javascript 复制代码
    <div>########################## start 全局自定义指令</div>
    <div>
        我是一个使用全局自定义指令的input:
        <input type="password" v-focus />
    </div>
    <div>########################## end 全局自定义指令</div>

效果:

3、 常用的自定义指令(后面有新的全局自定义指令封装会更新)

3.1 input获取焦点

src/directives/focus.js

javascript 复制代码
export default function(app) {
    app.directive('focus', {
        mounted(el) {
            console.log('focus指令, mounted')
            el.focus()
        },
    })
}

ts写法:

javascript 复制代码
// 获取焦点
export default function(app: any) {
app.directive("focus", {
    mounted(el: any) {
      console.log("focus mounted");
      el.focus();
    }
  })
}

3.2 防抖

src/directives/debounce.js

注册那一步和上面focus一样(此处及后面将省略)

javascript 复制代码
// 防抖
export default function (app) {
    app.directive('debounce', {
        mounted(el, binding) {
            console.log('el', el, 'binding', binding);
            let timer
            el.addEventListener('click', () => {
                if (timer) clearTimeout(timer)
                timer = setTimeout(() => {
                    binding.value()
                }, 2000)
            })
        },
    })
}

ts写法:

javascript 复制代码
// 防抖
export default function(app: any) {
  app.directive("debounce", {
    mounted(el: any, binding: any) {
      let timer:any
      el.addEventListener('click', () => {
        if (timer) {
          clearTimeout(timer)
        }
        timer = setTimeout(() => {
          binding.value()
        }, 1000)
      })
    }
  })
}

使用:

javascript 复制代码
<template>
    <div>
        我是测试防抖的全局自定义指令,
        如果在该间隔内再次触发,则重新计时。
        <button class="btn" v-debounce="testDebounceBtn" >防抖按钮:点击我,2秒后执行一次</button>
    </div>
</template>

<script setup>
 /**
  * 3、防抖自定义指令 --- 全局
  */
const testDebounceBtn = () => {
    console.log('防抖按钮:点击我,2秒内只执行一次')
}
</script>

效果:

点击按钮后2秒后执行,2秒内再次触发点击,将重新计时,重新计时后2秒后才执行。(正常开发时,时间按照实际情况设定,一般设定1秒后执行)

相关推荐
失忆爆表症18 分钟前
05_UI 组件库集成指南:Shadcn/ui + Tailwind CSS v4
前端·css·ui
小迷糊的学习记录20 分钟前
Vuex 与 pinia
前端·javascript·vue.js
发现一只大呆瓜31 分钟前
前端性能优化:图片懒加载的三种手写方案
前端·javascript·面试
不爱吃糖的程序媛42 分钟前
Flutter 与 OpenHarmony 通信:Flutter Channel 使用指南
前端·javascript·flutter
利刃大大43 分钟前
【Vue】Element-Plus快速入门 && Form && Card && Table && Tree && Dialog && Menu
前端·javascript·vue.js·element-plus
NEXT061 小时前
AI 应用工程化实战:使用 LangChain.js 编排 DeepSeek 复杂工作流
前端·javascript·langchain
念风零壹1 小时前
AI 时代的前端技术:从系统编程到 JavaScript/TypeScript
前端·ai
光影少年2 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
小毛驴8502 小时前
Vue 路由示例
前端·javascript·vue.js
发现一只大呆瓜2 小时前
AI流式交互:SSE与WebSocket技术选型
前端·javascript·面试