局部注册
先在setup中进行局部注册,如果使用Composition API
<script setup>
import { nextTick, ref } from 'vue';
const overflowIndexes = ref(new Set());
const handleOverflow = (index) => (el) => {
nextTick(() => {
if (el.scrollWidth > el.clientWidth) {
overflowIndexes.value.add(index);
} else {
overflowIndexes.value.delete(index);
}
});
};
// 自定义指令的名称和对象格式有一定的规范和要求(重点)
// v-overflow="handleOverflow(image.fileId)"调用时,binding.value为handleOverflow(image.fileId)函数
const vOverflow = {
mounted(el, binding) {
const callback = binding.value;
callback(el);
},
updated(el, binding) {
const callback = binding.value;
callback(el);
},
};
</script>
如果使用Options API
<script>
export default {
directives: {
overflow: {
mounted(el, binding) {
binding.value(el);
},
updated(el, binding) {
binding.value(el);
},
},
},
};
</script>
然后在template里使用
<el-tooltip :content="image.fileName" placement="top" :disabled="!overflowIndexes.has(image.fileId)">
<div v-overflow="handleOverflow(image.fileId)" class="p-1 text-base leading-5 truncate">
{{ image.fileName }}
</div>
</el-tooltip>
全局注册
import { createApp } from 'vue';
const vOverflow = {
mounted(el, binding) {
binding.value(el);
},
updated(el, binding) {
binding.value(el);
},
};
const app = createApp(App);
app.directive('overflow', vOverflow); // 全局注册
app.mount('#app');
使用方式跟局部注册的一样。
重点之一:Vue自定义指令对象的格式
const myDirective = {
// 1️⃣ 元素插入到 DOM 时调用 (只触发一次)
mounted(el, binding, vnode, prevVnode) {
console.log('mounted:', el, binding);
},
// 2️⃣ 组件更新时调用 (数据变化时触发)
updated(el, binding, vnode, prevVnode) {
console.log('updated:', el, binding);
},
// 3️⃣ 元素移除前调用
beforeUnmount(el, binding, vnode, prevVnode) {
console.log('beforeUnmount:', el, binding);
},
// 4️⃣ 元素移除后调用
unmounted(el, binding, vnode, prevVnode) {
console.log('unmounted:', el, binding);
}
};
其中binding是一个对象,包含如下指令的值等信息
binding = {
instance, // 调用该指令的组件实例
value, // 绑定的值,如 v-myDirective="myValue",则 value = myValue
oldValue, // 之前的值(仅在 updated 中可用)
arg, // 传递的参数,如 v-myDirective:arg,arg = "arg"
modifiers, // 修饰符,如 v-myDirective.modifier,modifiers = { modifier: true }
}
重点之二:Vue自定义指令名称的格式
推荐使用小驼峰(camelCase) Vue 自动将指令名称从 camelCase 转换为 短横线(kebab-case)。所以在js/ts中定义的vOverflow,可以在template中通过v-overflow调用。
具体转换规则:
- 小写字母保持不变
* mydirective → mydirective
- 大写字母前加 - 并转换为小写
* myDirective → my-directive
* mySuperDirective → my-super-directive
- 多个大写字母连续时,每个字母前都加 -
* myXMLParser → my-x-m-l-parser(一般避免这样写)
- 前导大写字母不受影响(Vue 习惯小写命名)
* MyDirective → -my-directive(但 Vue 指令通常不会这样写)
另外, 在Vue 指令、组件名称和prop传递时,名称格式也会从camelCase 自动转换为 kebab-case。
| 应用 | camelCase(JS/TS 内部) | kebab-case(Vue 模板中) |
|---|---|---|
指令 (**vOverflow**) | **vOverflow** | **v-overflow** |
组件 (**MyComponent**) | **MyComponent** | **<my-component />** |
Props (**myPropValue**) | **myPropValue** | **my-prop-value** |
事件 (**myEvent**) | **emit('myEvent')** | **@my-event="handleMyEvent"** |
插槽 (**mySlot**) | **#mySlot** | **#my-slot** |