Teleport
Vue3 新增了一个内置组件:Teleport。这个组件的作用主要用来将模板内的 DOM 元素移动到其他位置。
使用场景
业务开发的过程中,我们经常会封装一些常用的组件,例如 Modal 组件。相信大家在使用 Modal 组件的过程中,经常会遇到一个问题,那就是 Modal 的定位问题。
可能会发生弹窗组件的定位错乱的问题。
这个时候,使用 Teleport 组件就能解决这个问题了。
Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下呈现 HTML,而不必求助于全局状态或将其拆分为两个组件。 ----- 官方文档
我们只需要将弹窗内容放入 Teleport 内,并设置 to 属性为 body,表示弹窗组件每次渲染都会做为 body 的子级,这样之前的问题就能得到解决。
modal.vue
<template>
<teleport to="body">
<!--to = "app" 也可放到与app同级,to中放id-->
<div class="modal" v-if="isOpen">
<div id="center">
<h2>
<slot>this is a modal</slot>
</h2>
<button @click="clickButton">关闭模态框</button>
</div>
</div>
</teleport>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'modal',
props: {
isOpen: Boolean
},
emits:{
'close-modal':null
},
setup(props,cc){
const clickButton = ()=>{
cc.emit('close-modal')
}
return {
clickButton
}
}
});
</script>
<style scoped>
.modal{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0,0,0,.6);
}
#center {
width: 200px;
height: 200px;
border: 2px solid black;
background: white;
position: fixed;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -100px;
}
</style>
使用传送
App.vue
<<template>
<img alt="Vue logo" src="./assets/logo.png">
<modal :isOpen="modalisopen" @close-modal="onCloseModal">
插槽
</modal>
<div id="test"></div>
<button @click="openModal">打开模态框</button>
</template>
<script lang="ts">
import { defineComponent ,ref} from 'vue';
import modal from './components/modal.vue';
export default defineComponent({
name: 'App',
components: {
modal
},
setup(){
const modalisopen = ref(false)
const onCloseModal = ()=>{
modalisopen.value = false
}
const openModal = ()=>{
modalisopen.value = true
}
return {
modalisopen,
onCloseModal,
openModal
}
}
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>