自定义指令与 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 处理加载状态。

最后更新 4/30/2026, 8:57:45 AM