Vue3 自定义指令完整教程
Vue3 Banner

Vue3 自定义指令完全指南

掌握Vue3自定义指令的核心技术与实战应用

什么是Vue3自定义指令?

Vue3自定义指令是一种强大的功能,允许开发者直接操作DOM元素。与组件不同,指令更适合用于低级别的DOM操作。

自定义指令可以用于各种场景,如表单验证、图片懒加载、权限控制、动画效果等。Vue3中的指令API与Vue2相比有了一些变化,但核心概念保持一致。

提示: 指令特别适合封装那些需要在多个组件中重复使用的DOM操作逻辑。

Vue3指令概念

基础自定义指令

指令注册

在Vue3中注册全局指令和局部指令的方法:

// 全局指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 局部指令
const myDirective = {
  mounted(el, binding) {
    // 指令逻辑
  }
}

指令生命周期

Vue3指令的生命周期钩子:

  • beforeMount - 元素插入DOM前调用
  • mounted - 元素插入DOM后调用
  • beforeUpdate - 元素更新前调用
  • updated - 元素更新后调用
  • beforeUnmount - 元素卸载前调用
  • unmounted - 元素卸载后调用

指令参数

指令可以接收多种参数:

绑定值

<div v-my-directive="someValue"></div>

// 在指令中通过binding.value访问
mounted(el, binding) {
  console.log(binding.value) // => someValue
}

参数和修饰符

<div v-my-directive:arg.modifier="value"></div>

// 在指令中访问
mounted(el, binding) {
  console.log(binding.arg)    // => "arg"
  console.log(binding.modifiers) // => { modifier: true }
}

基础指令示例

1. 自动聚焦指令

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

2. 颜色指令

这段文字会变成红色

app.directive('color', {
  mounted(el, binding) {
    el.style.color = binding.value
  }
})

高级自定义指令

动态参数指令

指令参数可以是动态的:

<div v-pin:[direction]="200">固定位置元素</div>

data() {
  return {
    direction: 'top'
  }
}

app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  },
  updated(el, binding) {
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  }
})

函数简写

当只需要mounted和updated钩子时,可以使用简写:

app.directive('color', (el, binding) => {
  el.style.color = binding.value
})

// 等同于
app.directive('color', {
  mounted(el, binding) {
    el.style.color = binding.value
  },
  updated(el, binding) {
    el.style.color = binding.value
  }
})

对象字面量

指令可以接收对象字面量:

HTML示例

<div v-demo="{ color: 'white', text: 'hello!' }"></div>

指令实现

app.directive('demo', (el, binding) => {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

高级指令示例

1. 权限控制指令

app.directive('permission', {
  mounted(el, binding) {
    const userRole = 'user' // 实际应从store或API获取
    if (userRole !== binding.value) {
      el.style.display = 'none'
    }
  }
})

2. 图片懒加载指令

懒加载图片
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)
  }
})

实战案例

案例1

1. 点击外部关闭

实现点击元素外部时触发关闭逻辑的指令。

案例2

2. 复制到剪贴板

一键复制文本到剪贴板的指令实现。

案例3

3. 拖拽指令

使元素可拖拽的自定义指令实现。

拖拽我试试

更多实用指令

1. 防抖指令

app.directive('debounce', {
  mounted(el, binding) {
    let timer
    el.addEventListener('input', () => {
      clearTimeout(timer)
      timer = setTimeout(() => {
        binding.value()
      }, 500)
    })
  }
})

2. 长按指令

app.directive('longpress', {
  mounted(el, binding) {
    let pressTimer
    const start = (e) => {
      if (e.type === 'click' && e.button !== 0) return
      pressTimer = setTimeout(() => {
        binding.value()
      }, 1000)
    }
    const cancel = () => clearTimeout(pressTimer)
    
    el.addEventListener('mousedown', start)
    el.addEventListener('touchstart', start)
    el.addEventListener('click', cancel)
    el.addEventListener('mouseout', cancel)
    el.addEventListener('touchend', cancel)
    el.addEventListener('touchcancel', cancel)
  }
})

点击外部关闭演示

点击弹窗外部或关闭按钮可以关闭此弹窗。

这是通过v-click-outside指令实现的。

互动区域

登录后可以点赞此内容

参与互动

登录后可以点赞和评论此内容,与作者互动交流