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

相关推荐
卷帘依旧15 分钟前
SSE(Server-Sent Events)完全指南
前端
码云之上16 分钟前
万星入坞:我们如何用三层插件体系干掉巨石应用
前端·架构·前端框架
kyriewen21 分钟前
一口气讲清楚 Monorepo、Turborepo、pnpm、Changesets 到底是什么?
前端·架构·前端工程化
logo_2840 分钟前
Xpath语法规则的学习和使用
javascript·python·xpath·xpath语法
IT_陈寒1 小时前
React性能优化踩的坑,这个错你可能也会犯
前端·人工智能·后端
zhangxingchao1 小时前
AI应用开发三:RAG技术与应用
前端·人工智能·后端
摘星小杨2 小时前
如何在前端循环调取接口,实时查询数据
开发语言·前端·javascript
Hilaku2 小时前
从搜索排名到 AI 回答? 先聊一聊 AI 可见度工具 BuildSOM !
前端·javascript·程序员
zzmgc42 小时前
纯静态 + Web Worker + 虚拟滚动:我是怎么让浏览器吃下 10MB JSON 不卡的
前端·架构
辰同学ovo2 小时前
用 Chrome DevTools MCP 给 AI 写的页面做“质检“
前端·人工智能·chrome devtools