vue3中自定义指令使用

Vue 3 自定义指令详细使用指南

1. 基本结构

一个完整的自定义指令包含以下可选钩子函数:

javascript 复制代码
const myDirective = {
  // 指令第一次绑定到元素时调用(只调用一次)
  created(el, binding, vnode, prevVnode) {},
  
  // 元素插入父 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  
  // 元素插入父 DOM 后调用
  mounted(el, binding, vnode, prevVnode) {},
  
  // 父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  
  // 父组件和子组件都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  
  // 父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  
  // 父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

2.钩子函数参数

3.注册方式

3.1全局注册

javascript 复制代码
// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

app.mount('#app')

3.2 局部注册

javascript 复制代码
// 在组件中
export default {
  directives: {
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  }
}

4.使用方式

5.实用示例

5.1权限控制指令

javascript 复制代码
app.directive('permission', {
  mounted(el, binding) {
    const userPermissions = ['edit', 'view'] // 通常从store获取
    if (!userPermissions.includes(binding.value)) {
      el.style.display = 'none'
      // 或者直接移除元素
      // el.parentNode.removeChild(el)
    }
  }
})

5.2 防抖点击指令

javascript 复制代码
app.directive('debounce-click', {
  mounted(el, binding) {
    const delay = binding.value || 500
    let timer = null
    
    el.addEventListener('click', () => {
      if (timer) clearTimeout(timer)
      timer = setTimeout(() => {
        binding.arg && binding.arg()
      }, delay)
    })
  },
  unmounted(el) {
    el.removeEventListener('click')
  }
})

5.3 拖拽指令

javascript 复制代码
app.directive('drag', {
  mounted(el) {
    let isDragging = false
    let offsetX, offsetY
    
    el.style.position = 'absolute'
    el.style.cursor = 'move'
    
    el.addEventListener('mousedown', (e) => {
      isDragging = true
      offsetX = e.clientX - el.getBoundingClientRect().left
      offsetY = e.clientY - el.getBoundingClientRect().top
    })
    
    document.addEventListener('mousemove', (e) => {
      if (!isDragging) return
      el.style.left = e.clientX - offsetX + 'px'
      el.style.top = e.clientY - offsetY + 'px'
    })
    
    document.addEventListener('mouseup', () => {
      isDragging = false
    })
  }
})

5.4 图片懒加载指令

javascript 复制代码
app.directive('lazy', {
  mounted(el, binding) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          el.src = binding.value
          observer.unobserve(el)
        }
      })
    })
    observer.observe(el)
  }
})

6.注意事项

在 setup() 中定义的指令必须以 v 开头(如 vFocus),才能在模板中作为 v-focus 使用
指令必须从 setup() 中返回才能在模板中使用
对于需要清理的资源(如事件监听器),确保在 unmounted 钩子中进行清理
指令的 binding 参数是响应式的,但 el 不是
在 <script setup> 中定义的指令会自动暴露给模板,无需显式返回

相关推荐
ziyue757511 分钟前
vue修改element-ui的默认的class
前端·vue.js·ui
树叶会结冰32 分钟前
HTML语义化:当网页会说话
前端·html
冰万森38 分钟前
解决 React 项目初始化(npx create-react-app)速度慢的 7 个实用方案
前端·react.js·前端框架
牧羊人_myr1 小时前
Ajax 技术详解
前端
浩男孩1 小时前
🍀封装个 Button 组件,使用 vitest 来测试一下
前端
蓝银草同学1 小时前
阿里 Iconfont 项目丢失?手把手教你将已引用的 SVG 图标下载到本地
前端·icon
布列瑟农的星空1 小时前
重学React —— React事件机制 vs 浏览器事件机制
前端
程序定小飞2 小时前
基于springboot的在线商城系统设计与开发
java·数据库·vue.js·spring boot·后端
一小池勺2 小时前
CommonJS
前端·面试