局部注册
先在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 = myValueoldValue, // 之前的值(仅在 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** |