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秒后执行)

相关推荐
鬼手点金2 小时前
nanoGPT/nanochat 能做出 DeepSeek/Qwen 这样的大模型吗?
服务器·前端·javascript·bug·openclaw
软件技术NINI2 小时前
美妆商城html+Css+js 4页
javascript·css·html
蛋蛋的就会顺顺的2 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
程序员Sunday2 小时前
TypeScript 的 any、unknown、never 有什么区别?
前端·面试·typescript
朱涛的自习室2 小时前
70 美金的 Beyond Compare,我让 Gemini 4 和 DeepSeek 造个开源免费版(Day 2)
android·前端·人工智能
码艺-Alimjan3 小时前
Tauri 源码备份 · 打包 & 解压 总结,源码收集之路
前端·javascript·vue.js
小马不起床3 小时前
零基础玩转 FastAPI_11:前端后台管理页面
前端·状态模式·fastapi
子非鱼a4 小时前
【文件上传】一个普普通通的edu16
前端
美狐美颜SDK开放平台5 小时前
直播APP如何实现美白滤镜功能?视频美颜SDK技术开发方案详解
前端·数据库·人工智能·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
pride.li5 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉