Vue3新增内置组件之<Teleport/>,解决DOM层级问题

156 阅读1分钟

<Teleport> 将其插槽内容渲染到 DOM 中的另一个位置。 Teleport是一个内置组件,用来解决DOM结构层级的问题并且Teleport只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系

Props

 interface TeleportProps {
     to: string | HTMLElement // 必填项。指定目标可以是选择器或实际元素
     disabled?: boolean // 当值为true时,内容将保留在其原始位置,而不移动到目标容器中。可以动态更改
 }
 

示例

 <teleport to="#some-id" /> 
 <teleport to=".some-class" /> 
 <teleport to="[data-teleport]" />
 
 有条件地禁用:
 <teleport to="#popup" :disabled="displayVideoInline"> 
     <video src="./my-movie.mp4"> 
 </teleport>
 

举例说明,常见的全屏模态框

当在初始 HTML 结构中使用这个组件时,会有一些以下潜在的问题:

  • position: fixed 能够相对于浏览器窗口放置有一个条件,那就是不能有任何祖先元素设置了 "transform"、"perspective" 或者 "filter" 样式属性。也就是说如果我们想要用 CSS "transform" 为祖先节点 <div class="outer">设置动画,就会不小心破坏模态框的布局!

  • 这个模态框的 z-index受限于它的容器元素。如果有其他元素与 <div class="outer"> 重叠并有更高的 z-index,则它会覆盖住我们的模态框。

<script>
    <button @click="open = true">打开模态框</button>
    
    <div v-if="open" class="modal modal-demo"> 
        <p>Hello from the modal!</p> 
        <button @click="open = false">Close</button> 
    </div>
</script>
<style>
    .modal { 
        position: fixed; 
        z-index: 999; 
        top: 20%; 
        left: 50%; 
        width: 300px; 
        margin-left: -150px; 
       }
</style>

然而,这个内置组件就解决了以上的潜在问题

   <button @click="open = true">打开模态框</button>
    
   <Teleport to="body">
        <div v-if="open" class="modal modal-demo"> 
            <p>Hello from the modal!</p> 
            <button @click="open = false">Close</button> 
        </div>
    </Teleport>
        

查看Element,<div class="modal modal-demo"></div><body>标签下找到模态框元素
20220916-145130.jpg <Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue“把以下模板片段传送到 body 标签下”。