Teleport 把组件内容渲染到 DOM 树的其他位置(通常是 body),但保持组件的逻辑归属不变——弹窗、"> Teleport 把组件内容渲染到 DOM 树的其他位置(通常是 body),但保持组件的逻辑归属不变——弹窗、"> Teleport 把组件内容渲染到 DOM 树的其他位置(通常是 body),但保持组件的逻辑归属不变——弹窗、">
Vue 词条目录
前端Wiki/Vue/深入/组合式与内置组件

Teleport 与 Suspense

Teleport 把组件内容渲染到 DOM 树的其他位置(通常是 body),但保持组件的逻辑归属不变——弹窗、通知、下拉菜单不再受父级 overflow/z-index 限制,是写浮层的神器。

Suspense 处理异步组件/异步 setup 的加载态:包裹组件后,fallback 插槽在等待期间显示加载提示,加载完成自动切换。配合 defineAsyncComponent 做代码分割,首屏只加载必要代码。

  • Teleport to="body":浮层跳出父容器限制,逻辑仍属原组件
  • Suspense + fallback:异步组件加载态全自动管理
  • defineAsyncComponent(() => import(组件)) 实现按需加载
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Teleport 与 Suspense</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
  <div id="app">
    <!-- 父容器有 overflow:hidden,普通绝对定位会被裁掉 -->
    <div style="overflow:hidden;height:80px;border:1px solid #ddd;padding:8px">
      <button @click="open = true">打开弹窗</button>
      <p>弹窗已被 teleport 到 body,不受 hidden 影响</p>
    </div>

    <teleport to="body">
      <div v-if="open" style="position:fixed;top:20%;left:30%;padding:20px;
                  background:#fff;border:1px solid #42b883;box-shadow:0 8px 30px #0002">
        弹窗内容 <button @click="open = false">关闭</button>
      </div>
    </teleport>

    <!-- Suspense:异步组件加载时显示 fallback -->
    <suspense>
      <template #default><async-comp></async-comp></template>
      <template #fallback><p>加载中…</p></template>
    </suspense>
  </div>

<script>
  const { createApp, ref, defineAsyncComponent } = Vue;

  // 模拟异步组件:1 秒后才准备好
  const AsyncComp = defineAsyncComponent(() => {
    return new Promise((resolve) => {
      setTimeout(() => resolve({
        template: '<p style="color:#42b883">异步组件加载完成</p>'
      }), 1000);
    });
  });

  const app = createApp({
    setup() { return { open: ref(false) }; }
  });
  app.component('async-comp', AsyncComp);
  app.mount('#app');
</script>
</body>
</html>
本节要点Teleport 让浮层摆脱父容器限制;Suspense + defineAsyncComponent 管理异步加载与代码分割。