菜单

特殊组件

相关源文件

Vue.js 提供了几个内置的特殊组件,它们可以解决超越基本组件功能之外的特定 UI 需求。本文档涵盖了三个核心特殊组件:Teleport、KeepAlive 和 Suspense。这些组件分别负责控制 DOM 放置、组件缓存和异步渲染。

有关过渡和动画的信息,请参阅 过渡

目录

特殊组件概览

Vue.js 中的特殊组件是内置组件,它们提供的高级功能与数据渲染不直接相关,而是专注于控制组件行为和 DOM 结构。与常规组件不同,它们每个都有独特的内部标志(例如 __isTeleport__isKeepAlive__isSuspense),渲染器会识别并特殊处理它们。

来源

Teleport 组件

Teleport 允许您将组件内容渲染到 DOM 中的任何位置,无论组件在虚拟 DOM 层级中的哪个位置挂载。这对于模态框、工具提示和其他应在正常文档流之外渲染的覆盖元素特别有用。

API

disabled 为 true 时,Teleport 会在原始位置渲染内容。当 defer 为 true 时,Teleport 会等到初始渲染后才将内容移动到目标位置,这对于可能在初始渲染期间不存在的目标很有用。

来源

渲染机制

Teleport 在原始位置(占位符注释保留在此处)和目标位置(内容在此处渲染)之间维护一个虚拟连接。

来源

Teleport 如何在内部工作

  1. 挂载:

    • 在原始位置创建注释节点占位符
    • 使用选择器或直接引用查找目标元素
    • 将子元素移动到目标位置
  2. 更新:

    • 如果 to prop 更改,内容将被移动到新目标
    • 如果 disabled 更改为 true,内容将移回原始位置
    • 如果 disabled 更改为 false,内容将移到目标位置
  3. SSR 支持:

    • Teleport 的内容将渲染到单独的 Teleport 缓冲区中
    • 这些缓冲区将被注入到最终 HTML 的适当位置

来源

KeepAlive 组件

KeepAlive 会缓存不活跃的组件实例,而不是销毁它们。这可以在组件切换之间保留组件状态,避免昂贵的重新渲染,并跨组件停用/重新激活周期维护滚动位置或用户输入。

API

includeexclude prop 根据组件名称控制应缓存哪些组件。max prop 限制了可以同时缓存的组件实例数量(使用 LRU 驱逐)。

来源

KeepAlive 时的组件生命周期

KeepAlive 添加了两个额外的生命周期钩子

  • onActivated:当缓存的组件插入 DOM 时调用
  • onDeactivated:当组件从 DOM 中移除但保留在缓存中时调用

来源

KeepAlive 如何在内部工作

  1. 缓存机制:

    • 使用 Map 按键缓存 VNodes
    • 使用 Set 按 LRU 顺序跟踪键
    • 根据 include/exclude 模式和最大限制修剪缓存
  2. 停用流程:

    • 将组件移动到屏幕外容器,而不是销毁它
    • 调用停用钩子
    • 将组件标记为已停用
  3. 激活过程:

    • 检索缓存的 VNode
    • 将组件移回其原始位置
    • 调用激活钩子
    • 恢复组件状态

来源

Suspense 组件

Suspense 提供了一种在组件中处理异步依赖关系的方法,在所有异步操作完成之前显示回退内容。对于具有异步 setup 函数的组件或嵌套的异步组件,这尤其有用。

API

Suspense 提供两个插槽

  • default:包含具有潜在异步依赖关系的主组件
  • fallback:在等待异步操作时显示的后备内容

来源

Suspense 渲染流程

来源

Suspense 如何在内部工作

  1. 挂载阶段:

    • 尝试挂载默认内容
    • 跟踪挂载过程中遇到的异步依赖项
    • 如果检测到异步依赖项,则显示回退内容
    • 设置依赖项跟踪以进行解析
  2. 解析阶段:

    • 一旦所有异步依赖项都解析完毕,切换到默认内容
    • 可以通过超时进行配置,强制显示回退内容,即使依赖项解析很快
    • 可以使用 suspensible: true 冒泡到父 Suspense 组件
  3. 更新处理:

    • 处理组件在同步和异步状态之间切换的情况
    • 支持嵌套 Suspense 边界并进行适当协调

来源

集成模式

组合特殊组件

特殊组件可以组合起来创建强大的 UI 模式。以下是一些常见的组合

Teleport 与 KeepAlive

使用 Teleport 和 KeepAlive 时,请记住 KeepAlive 必须是它应缓存的组件的父组件,而不是 Teleport 的父组件

<!-- Correct: KeepAlive wraps component -->
<Teleport to="#modal">
  <KeepAlive>
    <MyComponent v-if="show" />
  </KeepAlive>
</Teleport>

<!-- Incorrect: KeepAlive wraps Teleport -->
<KeepAlive>
  <Teleport to="#modal">
    <MyComponent v-if="show" />
  </Teleport>
</KeepAlive>

Suspense 与异步组件

Suspense 与异步组件配合使用效果尤佳,在组件加载完成之前显示加载状态

<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <LoadingSpinner />
  </template>
</Suspense>

同构化注意事项

在服务器端渲染 (SSR) 期间,特殊组件具有特定的同构化行为

  • Teleport:内容将在 HTML 的目标位置渲染,但会维护虚拟连接
  • KeepAlive:在 SSR 期间表现为直通模式,因为缓存仅在客户端进行
  • Suspense:可以通过适当的回退内容来协调异步组件的同构化

来源

性能影响

每个特殊组件都有不同的性能特征

组件优点成本最佳实践
Teleport更清晰的 DOM 结构,保持上下文对 DOM 操作有轻微的开销用于需要特定定位的 UI 元素
KeepAlive避免昂贵的重新渲染,保留状态缓存组件的内存使用使用 max 限制缓存大小,使用 include/exclude
Suspense为异步组件提供更好的用户体验增加了组件树的复杂性对于简单的加载状态,请考虑其他选项

来源