Vue自定义指令:从入门到实战应用

一、自定义指令基础概念

官方文档:自定义指令

1.1 什么是自定义指令?

Vue自定义指令是对原生DOM操作的高级封装,用于扩展HTML元素的功能。它允许开发者创建可复用的DOM行为,主要应用于以下场景:

  • DOM底层操作(如聚焦、拖拽)
  • 集成第三方DOM库
  • 创建可视化特效

1.2 生命周期钩子

钩子函数 触发时机 典型应用场景
created 元素属性初始化时 访问初始化属性值
beforeMount 元素插入DOM前 预加载资源
mounted 元素插入DOM后 DOM操作(最常用)
beforeUpdate 绑定值更新前 保存旧状态
updated 绑定值更新后 响应数据变化
beforeUnmount 元素卸载前 清理定时器
unmounted 元素卸载后 移除事件监听

二、指令注册方式详解

2.1 全局注册

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

const app = createApp(App)

// 方式1:直接注册
app.directive('focus', { //focus指令
  mounted(el) {  //mounted时生效
    el.focus()
  }
})

// 方式2:模块化注册  //代码更加优雅
import draggable from './directives/draggable'
app.directive('draggable', draggable)

2.2 局部注册(组件级)

vue 复制代码
<script setup>
// 方式1:函数式指令
const vColor = (el, binding) => {
  el.style.color = binding.value
}

// 方式2:对象式指令
const vHighlight = {
  mounted(el, binding) {
    el.style.backgroundColor = binding.value
  },
  updated(el, binding) {
    el.style.backgroundColor = binding.value
  }
}
</script>

三、实战案例解析

3.1 案例一:元素拖拽指令

3.1.1. 定义指令

js 复制代码
// 定义自定义指令
export default {
  mounted(el) {
    // 鼠标放上去时,改变鼠标样式为"move"
    el.style.cursor = 'move'
    el.style.position = 'relative'

    // 监听鼠标按下事件
    el.onmousedown = function(e) {
      // 获取鼠标按下时相对元素的偏移
      let disX = e.pageX - el.offsetLeft
      let disY = e.pageY - el.offsetTop

      // 监听鼠标移动事件
      document.onmousemove = function(e) {
        let x = e.pageX - disX
        let y = e.pageY - disY

        // 边界检测
        let maxX = document.body.clientWidth - el.offsetWidth
        let maxY = document.body.clientHeight - el.offsetHeight

        // 限制元素在页面中的最大和最小位置
        if (x < 0) x = 0
        if (x > maxX) x = maxX
        if (y < 0) y = 0
        if (y > maxY) y = maxY

        // 设置元素的新位置
        el.style.left = `${x}px`
        el.style.top = `${y}px`
      }

      // 监听鼠标释放事件
      document.onmouseup = function() {
        // 取消事件
        document.onmousemove = null
        document.onmouseup = null
      }
    }
  }
}

3.1.2. 注册指令

指令的定义需要一个install函数,该函数用于注册指令到Vue实例中。Vue会调用install函数来将指令注册到全局或局部。

js 复制代码
//  ./command/index.js'
import Draggable from './draggable.js'
// 统一注册
const directive = {
  Draggable
  //...
  //...
}

export default {
  install(app) {
    // 注册自定义指令
    Object.keys(directive).forEach(key => {
      app.directive(key, directive[key])  //指令需要通过`app.directive`来注册。
    })
  }
}

然后在main.js中挂载。

js 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import Directives from './command/index.js'

const app = createApp(App)
app.use(Directives) // 全局注册 // 注册指令use调用了install 函数,触发注册
app.mount('#app')

3.1.3. 在组件中使用指令

自定义指令注册后,你就可以在模板中使用它了。假设你创建了一个v-draggable指令来使元素可拖拽,下面是如何使用它的示例:

vue 复制代码
<template>
  <div class="box" v-draggable></div>
</template>

<script setup>
// 这里不需要特别的代码,因为指令已经在全局注册过
</script>

<style lang="css" scoped>
.box {
  width: 100px;
  height: 100px;
  background-color: #f00;
}
</style>

3.2 案例二:动态颜色指令

javascript 复制代码
// 对象式写法(推荐)
export default {
// el:该指令绑定在哪个元素上   binding:指令的相关信息,包含该指令绑定的值
  mounted(el, binding) {  
    updateColor(el, binding.value);
  },
  updated(el, binding) {
    updateColor(el, binding.value);
  }
}

// 函数式写法(同时触发mounted和updated)
// export default (el, binding) => {
//   updateColor(el, binding.value)
// }

function updateColor(el, value) {
  const length = value?.length || 0;
  
  if (length <= 5) {
    el.style.color = 'green';
  } else if (length <= 10) {
    el.style.color = 'goldenrod';
  } else {
    el.style.color = 'red';
  }
}

3.1.3. 使用示例

vue 复制代码
<template>
  <div class="input-group">
    <input 
      type="text" 
      v-model="inputVal"
      placeholder="输入内容观察颜色变化"
    >
    <h3 v-highlight="inputVal">{{ inputVal }}</h3>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const inputVal = ref('');
</script>

<style>
.input-group {
  margin: 20px;
  padding: 15px;
  border: 1px solid #eee;
}

h3 {
  transition: color 0.3s;
  padding: 10px;
  border-radius: 4px;
}
</style>
相关推荐
不停喝水5 分钟前
【前端转全栈java速通课】 项目实战④-1 Spring Boot 创建项目-定义接口-请求参数处理-分层规范-依赖注入
java·前端·spring boot
用户298698530147 分钟前
在 React 中使用 JavaScript 将 HTML 转换为 PDF
javascript·react.js·html
OpsEye15 分钟前
企业如何统一管理多家大模型 API?
javascript·ai编程
涛涛ing16 分钟前
当AI能写原生代码:Shopify用12周把React Native应用迁回了Swift和Kotlin
前端
JudithHuang25 分钟前
React 数据请求:TanStack Query
前端·react.js·前端框架
程序员-Benothing29 分钟前
Shell脚本入门教程:Shebang、变量、注释与执行方式
前端·chrome
java_nnnn34 分钟前
JavaEE进阶-JavaScript初识
开发语言·前端·javascript·java-ee·ecmascript
裕晟资质规划1 小时前
涉密场所物理隔离与技术防护体系:标准矩阵、审查校验点与常见缺陷分析
大数据·前端·网络·人工智能·经验分享
变与不变8061 小时前
JSON基础详解
前端·javascript
吴声子夜歌1 小时前
HTML——结构化微数据语言简介
前端·数据库·html