Vue 自定义指令的使用方法
Vue 自定义指令(Directives)用于 直接操作 DOM,它们的功能类似于 Vue 内置指令(如 v-if
、v-show
、v-model
),但可以自定义行为,比如 权限控制、输入限制、拖拽、自动聚焦等。
1. 自定义指令的基本用法
(1)局部指令
在 Vue 组件 内部定义和使用:
<script setup>
import { onMounted } from "vue";
const vFocus = {
mounted(el) {
el.focus(); // 指令绑定的元素会自动获取焦点
}
};
</script>
<template>
<input v-focus placeholder="自动聚焦输入框" />
</template>
📌 作用:输入框在页面加载时自动获取焦点。
(2)全局指令
在 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");
然后 在任何组件中使用:
<input v-focus placeholder="自动聚焦输入框" />
2. 自定义指令的生命周期钩子
Vue 自定义指令支持多个 生命周期钩子:
钩子 | 触发时机 |
---|---|
created | 指令绑定到元素上(仅调用一次)。 |
beforeMount | 在元素插入 DOM 之前调用(适用于初始化逻辑)。 |
mounted | 元素插入 DOM 后调用(适用于操作 DOM)。 |
beforeUpdate | 绑定元素的父组件更新前调用(适用于动态内容)。 |
updated | 绑定元素的父组件更新后调用(适用于动态内容)。 |
beforeUnmount | 元素被卸载前调用(适用于清理事件)。 |
unmounted | 元素被卸载后调用(适用于清理 DOM 资源)。 |
📌 示例:指令完整写法
app.directive("demo", {
created(el, binding) {
console.log("created:", binding.value);
},
beforeMount(el) {
console.log("beforeMount");
},
mounted(el) {
console.log("mounted");
},
beforeUpdate(el) {
console.log("beforeUpdate");
},
updated(el) {
console.log("updated");
},
beforeUnmount(el) {
console.log("beforeUnmount");
},
unmounted(el) {
console.log("unmounted");
}
});
然后在组件中:
<p v-demo="'hello'">自定义指令测试</p>
控制台会输出 created: hello
、mounted
等日志。
3. 自定义指令的参数与动态值
(1)指令绑定值
指令可以接收一个值,如:
<input v-focus="true" />
app.directive("focus", {
mounted(el, binding) {
if (binding.value) {
el.focus(); // 只有当传入值为 true 时才聚焦
}
}
});
(2)指令修饰符
修饰符是指令中的 .
号后缀,类似 v-model.trim
。
<input v-uppercase.focus />
app.directive("uppercase", {
mounted(el, binding) {
el.addEventListener("input", () => {
el.value = el.value.toUpperCase(); // 转大写
});
if (binding.modifiers.focus) {
el.focus(); // 如果有 .focus 修饰符,则自动聚焦
}
}
});
4. 实战案例
(1)RBAC 权限控制指令
import { useUserStore } from "@/store/user";
export default {
mounted(el, binding) {
const userStore = useUserStore();
const permissions = userStore.permissions || [];
const requiredPermissions = binding.value;
if (!permissions.includes(requiredPermissions)) {
el.parentNode && el.parentNode.removeChild(el);
}
}
};
📌 用法
<button v-permission="'delete'">删除</button>
如果用户没有 "delete"
权限,按钮会被移除。
(2)图片懒加载 v-lazy
app.directive("lazy", {
mounted(el, binding) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
el.src = binding.value; // 加载图片
observer.unobserve(el); // 只触发一次
}
});
observer.observe(el);
}
});
📌 用法
<img v-lazy="'https://example.com/image.jpg'" />
✅ 只有图片进入视口才会加载,提高性能。
(3)防抖输入框 v-debounce
app.directive("debounce", {
mounted(el, binding) {
let timer;
el.addEventListener("input", () => {
clearTimeout(timer);
timer = setTimeout(() => {
binding.value(); // 触发回调
}, 500);
});
}
});
📌 用法
<input v-debounce="onInput" />
function onInput() {
console.log("输入完成!");
}
✅ 输入停止 500ms 后才触发回调,避免频繁触发 API。
总结
✅ 基本使用:
- 局部注册:直接在组件
setup()
内定义。 - 全局注册:在
main.js
中注册,全项目可用。
✅ 生命周期钩子:
mounted
:操作 DOM。updated
:动态更新。
✅ 应用场景:
- 权限控制:
v-permission
- 图片懒加载:
v-lazy
- 输入防抖:
v-debounce
- 自动聚焦:
v-focus
- 文本转换:
v-uppercase
🚀 自定义指令可以极大提升 Vue 开发的可复用性!