vue3 teleport的使用
teleport是什么
官网介绍:Renders its slot content to another part of the DOM,翻译过来就是将其插槽内容呈现给DOM
的另一部分。
teleport使用场景
比如一些弹框(公共组件嵌套太多)、loading
页面可以使用其避免css
被外层父组件样式影响。
下面我们以loading
页面来了解它。
我们先正常写一个loading
页面,看到以下DOM
结构:
有时候它可能会被父元素的样式影响,所以我们可以使用teleport
来传送到最外层。
但此时呢,我们还需要手动去创建一个DOM
元素,来存放它,这样会比较的麻烦。那么我们就想到了在setup
(组件还没完成渲染,在DOM
完成渲染之前,手动创建一个DOM
节点)中去创建节点。
完整代码如下(其中使用了bootstrap
):
<template>
/* 传送到id为back的元素下 */
<teleport to="#back">
<div
class="d-flex justify-content-center align-items-center h-100 w-100 loading-container"
:style="{backgroundColor: background || ''}"
>
<div class="loading-content">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">{{ text || 'loading'}}</span>
</div>
<p v-if="text" class="text-primary small">{{text}}</p>
</div>
</div>
</teleport>
</template>
<script lang="ts">
import { defineComponent, onUnmounted } from 'vue'
export default defineComponent({
props: {
text: {
type: String
},
background: {
type: String
}
},
setup() {
// 在setup中创建节点
const node = document.createElement('div')
node.id = 'back'
document.body.appendChild(node)
// 在销毁前清除节点
onUnmounted(() => {
document.body.removeChild(node)
})
}
})
</script>
<style>
.loading-container {
background: rgba(255, 255, 255, .5);
z-index: 100;
position: fixed;
top: 0;
left: 0;
}
.loading-container {
text-align: center;
}
</style>
使用:
<template>
<div class="container">
<loader :background="'rgba(0, 0, 0, 0.8)'" :text="'加载中...'"></loader>
</div>
</template>
<script lang="ts">
import 'bootstrap/dist/css/bootstrap.min.css'
import Loader from './components/Loader.vue'
export default {
name: 'App',
components: {
Loader
},
}
</script>
使用之后便已经在顶层另一个单独DOM
元素中了,如下: