这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战
vue3 中新增了一个 teleport 组件 ,记录一下学习的知识点。
Vue 官方释义:Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下呈现 HTML,而不必求助于全局状态或将其拆分为两个组件。
实话说第一次看到这个解释的时候其实还是有些懵的,但参考了一些其他的资料才终于搞明白了一点。
什么是 teleport
我们通过一个比较常见的场景来解释一下啊,比如我们需要做一个弹窗的效果,那么我们通常会封装一个弹窗的组件然后通过事件来控制弹窗的显隐。如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难。
场景还原
我们先写一个简单的 modal 组件
<button @click="showToast" class="btn">打开 toast</button>
<!-- to 属性就是目标位置 -->
<teleport to="#teleport-target">
<div v-if="visible" class="toast-wrap">
<div class="toast-msg">我是一个 Toast 文案</div>
</div>
</teleport>
import { ref } from 'vue';
export default {
setup() {
// toast 的封装
const visible = ref(false);
let timer;
const showToast = () => {
visible.value = true;
clearTimeout(timer);
timer = setTimeout(() => {
visible.value = false;
}, 2000);
}
return {
visible,
showToast
}
}
}
然后我们在页面中引入 Modal 组件。
<template>
<div id="app"></div>
<div id="teleport-target"></div>
<hello-world></hello-world>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
效果展示:
可以看到,我们使用 teleport 组件,通过 to 属性,指定该组件渲染的位置与 <div id="app"></div> 同级,也就是在 body 下,但是 teleport 的状态 visible 又是完全由内部 Vue 组件控制。
注意:Props
to-string。需要 prop,必须是有效的查询选择器或 HTMLElement (如果在浏览器环境中使用)。指定将在其中移动<teleport>内容的目标元素
<!-- 正确 -->
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />
<!-- 错误 -->
<teleport to="h1" />
<teleport to="some-string" />
disabled-boolean。此可选属性可用于禁用<teleport>的功能,这意味着其插槽内容将不会移动到任何位置,而是在你在周围父组件中指定了<teleport>的位置渲染。
<teleport to="#popup" :disabled="displayVideoInline">
<video src="./my-movie.mp4">
</teleport>
请注意,这将移动实际的 DOM 节点,而不是被销毁和重新创建,并且它还将保持任何组件实例的活动状态。所有有状态的 HTML 元素 (即播放的视频) 都将保持其状态。