本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-02-26
有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
一个常见的场景是创建一个包含全屏模式的组件(比如一个模态框)。在大多数情况下,你希望模态框的逻辑存在于组件中,但是模态框的快速定位就很难通过 CSS 来解决,或者需要更改组件组合。
<template>
<div>
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
</div>
</template>
to="body"
告诉 Vue “Teleport 这个 HTML 到该body
标签”。Vue 将正确地将模态框内容渲染为 body 标签的子级。就做到了模态框的逻辑存在于组件中,同时也做到了父级元素的position: relative
影响不到模态框的 position: absolute
。
to 属性,必须是有效的查询选择器或 HTMLElement(如果在浏览器环境中使用)。指定将在其中移动 <teleport>
内容的目标元素
disabled 属性,可用于禁用 <teleport>
的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了 <teleport>
的位置渲染。
<teleport to="#popup" :disabled="displayVideoInline">
<video src="./my-movie.mp4">
</teleport>
请注意,这将移动实际的 DOM 节点,而不是被销毁和重新创建,并且它还将保持任何组件实例的活动状态。所有有状态的 HTML 元素 (即播放的视频) 都将保持其状态。
如果 <teleport>
包含 Vue 组件,则它仍将是 <teleport>
父组件的逻辑子组件:
app.component('parent-component', {
template: `
<h2>This is a parent component</h2>
<teleport to="#endofbody">
<child-component name="John" />
</teleport>
`
})
在这种情况下,即使在不同的地方渲染 child-component,它仍将是 parent-component 的子级,并将从中接收 name prop。这也意味着来自父组件的注入按预期工作,并且子组件将嵌套在 Vue Devtools 中的父组件之下,而不是放在实际内容移动到的位置。
在同一目标上使用多个 teleport,多个 <teleport>
组件可以将其内容挂载到同一个目标元素。顺序将是一个简单的追加——稍后挂载将位于目标元素中较早的挂载之后。
<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals">
<div>B</div>
</teleport>
<!-- result-->
<div id="modals">
<div>A</div>
<div>B</div>
</div>