自定义指令与 Teleport
自定义指令与 Teleport
Vue 内置了很多指令,但有时候需要自定义。这篇说自定义指令和 Teleport。
自定义指令
全局注册
// main.ts
app.directive('focus', {
mounted(el) {
el.focus()
}
})
局部注册
<script setup lang="ts">
const vFocus = {
mounted(el: HTMLElement) {
el.focus()
}
}
</script>
使用
<input v-focus />
指令的生命周期
| 钩子 | 时机 |
|---|---|
created | 元素创建后 |
beforeMount | 挂载前 |
mounted | 挂载后 |
beforeUpdate | 更新前 |
updated | 更新后 |
beforeUnmount | 卸载前 |
unmounted | 卸载后 |
传参
app.directive('highlight', {
mounted(el, binding) {
el.style.backgroundColor = binding.value
},
updated(el, binding) {
el.style.backgroundColor = binding.value
}
})
<p v-highlight="'yellow'">高亮文本</p>
修饰符:
app.directive('resize', {
mounted(el, binding) {
if (binding.modifiers.large) {
el.style.fontSize = '20px'
}
}
})
<p v-resize.large>大字文本</p>
Teleport
Teleport 让你把组件渲染到 DOM 树的任意位置,常用于弹窗、模态框。
问题
弹窗组件在嵌套层级很深时,样式可能被父组件影响,z-index 也难控制。
解决
<template>
<button @click="show = true">打开弹窗</button>
<Teleport to="body">
<div v-if="show" class="modal">
<p>这是一个弹窗</p>
<button @click="show = false">关闭</button>
</div>
</Teleport>
</template>
to="body" 把弹窗内容渲染到 <body> 下,不受父组件样式影响。
禁用
<Teleport to="body" :disabled="!isMobile">
<div class="modal">...</div>
</Teleport>
多个 Teleport 到同一目标
多个 Teleport 的内容会按顺序追加到目标元素内。
组合使用:自定义指令 + Teleport 弹窗
app.directive('modal', {
mounted(el, binding) {
if (binding.value) {
document.body.appendChild(el)
}
},
unmounted(el) {
el.remove()
}
})
总结
- 自定义指令用
app.directive全局注册,或在<script setup>中局部注册 - 指令钩子:mounted、updated、unmounted 等
- Teleport 把组件传送到任意 DOM 位置,常用于弹窗
to="body"最常用,避免样式冲突和 z-index 问题
下篇讲异步组件和 Suspense 处理加载状态。
