「这是我参与2022首次更文挑战的第41天,活动详情查看:2022首次更文挑战」。
我在写关于Vue3新特性系列的文章,今天的主要讲讲在Vue3中新特性中的Teleport。
Vue3中,Teleport组件的作用主要是用来将模版内的DOM元素移动到其他位置。类似于react中的Portals,Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。
在平时的项目中,我们会将可复用的逻辑设计或结构等,抽成组件。在 Vue中,使用template字符串或render函数在组件中构建 HTML DOM。 Vue 编译器会编译它并制作 div 元素。 但是,有时从逻辑上讲,我们需要一个组件,它可以是其父组件的子组件,但组件 HTML div 不应嵌套到其父组件。同时,我们需要将它放在 DOM 中的其他位置。这样就有点乱。
通常 HTML 树结构将与组件树结构相同。但是如果想在 DOM 中的其他地方更改一个组件 div 的父级,可以在 Vue.js 中使用 Teleport。它是 Vue.js 3 中引入的一个高级特性。
Teleport的两个属性。
Teleport 是移动实际的 DOM 节点,而不是重新创建它。这将保持相同的组件实例,Teleport有两个属性。
to - string 是一个prop,表示传送将移动其内容的目标父元素。这是一个强制性的props。这个props可以是一个有效的查询选择器,或者一个 HTML 元素(例如:body)。
<teleport to="#to-parent-id" />
<teleport to=".to-parent-id" />
<teleport to="[to-parent-data-teleport]" />
disabled - boolean是一个禁用传送操作的prop。这是一个可选的 boolean props。如果我们应用disable props,这将不会把传送的内容移到目标元素上。同时,它将渲染你指定了传送标签的元素,就像普通组件一样。
下面的示例,以弹出式或正常方式播放视频。
<teleport to="#popup" :disabled="popupOrInline">
<video src="./my-movie.mp4">
</teleport>
Vue 3 Teleport示例
在上面的示例中,在 Teleport 组件中使用了子组件 TeleportChild.vue。在这里,逻辑上 TeleportChild.vue 组件将保留为 TeleportComp.vue 组件的子组件,即使它的位置发生了变化(但实际上不是)。
// TeleportComp.vue
<template>
<div>
<teleport :to="teleportTo" :disabled="disableTeleport">
<TeleportChild:imagePath="imagePath" />
</teleport>
</div>
</template>
<script>
import TeleportChild from "./TeleportChild.vue";
export default {
components: {
TeleportChild,
},
props: {
teleportTo: {
type: String,
default: "body",
},
imagePath: String,
disableTeleport: Boolean,
},
};
</script>
// TeleportChild.vue
<template>
<img
:src="imagePath"
alt="Teleport child Text"
:style="{ width: '100%', height: '100%' }"
/>
</template>
<script>
export default {
props: {
imagePath: String,
altText: String,
},
};
</script>
在下面的示例中,如果 disableTeleport 设置为 true,则 Teleport 组件充当普通组件。如果 disableTeleport 设置为 false,teleport 组件将被移动到 #toPlace div 元素。 Teleport 不会在逻辑上改变组件树结构的层次结构。但效果会反映在 HTML DOM 中。现在图像元素移动到#toPlace 元素。
// TeleportDemo.vue
<template>
<div id="toPlace"></div>
<div :style="{ width: '200px', height: '200px' }">
<button class="btn" @click="onClickBtn">
{{ disableTeleport ? "Move to toPlace" : "Come Back" }}
</button>
<TeleportComp
teleportTo="#toPlace"
imagePath="logo_transparent.png"
:disableTeleport="disableTeleport"
/>
</div>
</template>
<script>
import { ref } from "vue";
import TeleportComp from "../components/teleport/TeleportComp.vue";
export default {
components: {
TeleportComp,
},
setup() {
let disableTeleport = ref(true);
const onClickBtn = () => {
disableTeleport.value = !disableTeleport.value;
};
return {
onClickBtn,
disableTeleport,
};
},
};
</script>
<style scoped>
#toPlace {
width: 200px;
height: 200px;
margin: auto;
display: flex;
justify-content: center;
}
.btn {
background-color: #4999f5;
border: none;
color: white;
padding: 10px;
font-size: 16px;
cursor: pointer;
}
.btn:hover {
background-color: #0417c0;
color: white;
}
</style>
多个Teleport示例
现在我们将看到多个传送操作。这里同一个目标元素将有多个Teleport组件。当我们移动Teleport组件时,它会按照移动顺序附加到目标元素上。
<teleport to="#toPlace">
<div>A</div>
</teleport>
<teleport to="#toPlace">
<div>B</div>
</teleport>
<!-- result-->
<div id="toPlace">
<div>A</div>
<div>B</div>
</div>
在上面的示例中,#toPlace 元素在传送操作时将具有 A、B div 元素。现在我们正在创建 TeleportMultipleDemo.vue 文件,其中我们将两个传送组件移动到相同的 #toPlace 目标元素。
总结
1.Teleport 将更改组件的父级。需要注意的是,teleport 移动的是实际的 DOM 节点,而不是重新创建。 2。即使 Teleport 更改了父元素,它也会保留组件的实例。 3.如果给定 disabled ,Teleport会将像普通组件一样呈现指定 teleport 标签的元素。 4.同一个目标元素可有多个传送组件。