【vue】07.自定义指令
一.什么是自定义指令
在了解什么是自定义指令前,需要知道什么是指令。vue
中提供了一套为数据驱动视图更为方便的操作,这些操作被称为指令系统。我们看到的v-
为前缀的行内属性,都是指令,它们各自执行特定的功能。此外,Vue还允许开发者创建自定义指令,包括定义全局或局部的指令,这些指令可以在模板中直接操作DOM元素,对 DOM 元素进行底层操作。
二.为什么要使用自定义指令
使用自定义指令可以将复杂的DOM操作封装成可复用的指令,从而提高代码的抽象程度、解耦逻辑,并增强模板的声明式编程能力。简单来说,就是把一些通用的DOM操作封装起来,方便使用。使用自定义指令有一些优点:
- 抽象和复用。将复杂的操作封装起来,然后在不同的组件中重复使用,不必每次都重写相同的逻辑。
- 简洁。因为自定义指令经与特定 DOM 操作相关的代码从组件的逻辑中分离了出来,将逻辑进行解耦,所以有利于保持组件的简洁性。
- 提高可读性。定义指令时最好语义化一些,便于其他开发者阅读代码时,通过指令名称快速理解其作用。
- 易于维护。当需要修改或优化 DOM 操作时,只需更新自定义指令的定义,而不必触及每个使用该指令的组件。
- 易于共享。自定义指令可以跨组件共享,也就是在多个组件之间可以共享相同的 DOM 操作逻辑。
三.如何使用自定义指令
1.定义全局自定义指令
顾名思义,全局自定义指令就是指在应用的任何组件中都可以使用的指令。要定义一个自定义指令,可以使用.directive方法。
举个例子:
import { createApp } from 'vue';
const app = createApp({});
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus();
}
});
app.mount('#app');
在上面的例子中,我定义了一个名为v-focus
的全局指令,它会在元素挂载到DOM后自动聚焦该元素。
再举一个例子:
例子逻辑:
首先创建一个ButtonCounter
组件,该组件包含一个按钮和一个计数器,每次点击按钮时,计数器会增加。
<!-- ButtonCounter.vue -->
<template>
<div>
<button @click="count++">点击我数量就会增加 {{ count }}</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
然后,在主文件中(例如main.js
或main.ts
)使用app.component()
方法来注册这个全局组件:
// main.js
import { createApp } from 'vue';
import ButtonCounter from './components/ButtonCounter.vue';
const app = createApp({});
// 注册全局组件
app.component('ButtonCounter', ButtonCounter);
app.mount('#app');
2.定义局部自定义指令
局部自定义指令只能在定义它的组件内部使用。在组件的directives
选项中定义局部指令。
import { createApp } from 'vue';
const app = createApp({});
app.component('MyComponent', {
directives: {
// 注册一个局部自定义指令 `v-focus`
focus: {
// 指令的定义
mounted(el) {
el.focus();
}
}
}
});
app.mount('#app');
3.在模板中的使用
全局自定义组件的第二个例子在模板中的使用如下:
<!-- 在其他组件的模板中使用 ButtonCounter -->
<template>
<div>
<h1>全局注册组件例子</h1>
<ButtonCounter />
</div>
</template>
每次点击ButtonCounter
组件中的按钮时,计数器的值都会增加。
四.自定义指令的应用场景
自定义指令的应用场景很广泛,这里列出几个典型应用场景。
1.自动聚焦输入框:当页面加载时,自动将焦点设置到某个输入框上,如上面的 v-focus
指令。
2.拖放元素: 创建一个自定义指令来处理元素的拖放功能。
app.directive('draggable', {
mounted(el) {
el.draggable = true;
el.ondragstart = (event) => {
// 处理拖动逻辑
};
}
});
3.懒加载图片: 创建一个自定义指令来延迟加载图片,直到它们进入视口。
app.directive('lazyload', {
mounted(el) {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
el.src = el.dataset.src;
observer.unobserve(el);
}
},
{ threshold: 0.1 }
);
observer.observe(el);
}
});
4.权限控制: 根据用户权限显示或隐藏元素。
app.directive('auth', {
mounted(el, binding) {
if (!hasPermission(binding.value)) {
el.parentNode.removeChild(el);
}
}
});
5.全屏切换: 创建一个指令来切换元素的全屏状态。
app.directive('fullscreen', {
mounted(el, binding) {
if (binding.value) {
el.requestFullscreen();
} else {
document.exitFullscreen();
}
}
});
6.格式化输入: 对输入框的值进行格式化,例如货币格式化。
app.directive('format-currency', {
updated(el, binding) {
const value = binding.value;
el.value = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(value);
}
});
到此结束。