vue3 teleport的使用案例詳解
官網(wǎng)
https://cli.vuejs.org/zh/guide/
有時(shí)組件模板的一部分邏輯上屬于該組件,而從技術(shù)角度來看,最好將模板的這一部分移動(dòng)到 DOM 中 Vue app 之外的其他位置。
案例


這兩個(gè)組件都是在父元素里的,是父組件的子級(jí),但是從技術(shù)角度來看,他們是應(yīng)該是掛載在body下面的
未修改版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue3</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="hello-vue" class="box">
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<button @click="handleClick">點(diǎn)我顯示子組件</button>
<cpn ref="compRef" @show-confirm="showConfirm"></cpn>
<confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="確定退出嗎"></confirm>
</div>
<!--點(diǎn)擊按鈕后顯示的那個(gè)組件-->
<template id="mycpn">
<transition name="list-fade">
<div class="cpnContainer" v-show="isshow" @click.stop="handleClose()">
<div class="inner-wrapper" @click.stop>
用到了transition
<div class="text">
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
</div>
<div class="close" @click="handleClose()">close</div>
</div>
</div>
</transition>
</template>
<!--確認(rèn)關(guān)閉confirm組件-->
<template id="confirm">
<transition name="confirm-fade">
<div v-show="isshow" class="confirm">
<div class="confirm-wrapper">
<div class="confirm-content">
<p>{{text}}</p>
<div class="btnContainer">
<button style="background-color: darkseagreen;margin-right: 40px" @click="confirm">{{confirmBtnText}}</button>
<button @click="cancel">{{cancelBtnText}}</button>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
const cpn = {
template: "#mycpn",
props: {},
data() {
return {
// bbb: 145612
isshow: false
}
},
methods: {
show() {
this.isshow = true
},
hide() {
// console.log("hide")
this.isshow = false
},
handleClose() {
// console.log("hide")
this.$emit("show-confirm")
},
}
}
const confirm = {
template: "#confirm",
props: {
text: {
type: String,
default: 'fdsafdasfdas'
},
confirmBtnText: {
type: String,
default: '確定'
},
cancelBtnText: {
type: String,
default: '取消'
}
},
data() {
return {
// bbb: 145612
isshow: false
}
},
methods: {
show() {
this.isshow = true
},
hide() {
this.isshow = false
// 控制子組件的顯示
},
// 點(diǎn)擊按鈕后向父組件派發(fā)事件
confirm() {
this.hide();
this.$emit("confirm")
},
cancel() {
this.hide()
this.$emit('cancel')
}
}
}
const HelloVueApp = Vue.createApp({
data() {
return {
message: 'Hello Vue!!'
}
},
components: {
cpn,
confirm
},
methods: {
handleClick() {
// 父組件調(diào)用子組件的方法
// this.$refs.compRef.show()
this.$refs.compRef.show()
},
showConfirm() {
console.log("fdsa")
this.$refs.confirmRef.show()
},
// 點(diǎn)擊取消或確定以后的邏輯
handleConfirm() {
this.$refs.compRef.hide()
},
handleCancel() {
}
}
}).mount("#hello-vue")
</script>
</body>
<style>
* {
font-size: 50px;
}
/*vue內(nèi)置transition*/
.list-fade-enter-active, .list-fade-leave-active {
transition: opacity .3s;
}
.list-fade-enter-active .inner-wrapper, .list-fade-leave-active .inner-wrapper {
transition: all .3s;
}
.list-fade-enter-from, .list-fade-leave-to {
opacity: 0;
}
.list-fade-enter-from .inner-wrapper, .list-fade-leave-to .inner-wrapper {
transform: translate3d(0, 100%, 0);
}
/*子組件樣式*/
.cpnContainer {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .3);
}
.inner-wrapper {
padding: 70px;
background-color: darkcyan;
position: fixed;
bottom: 0;
width: 100%;
box-sizing: border-box;
}
.close {
position: absolute;
top: 50px;
right: 50px;
}
/*confirm組件樣式*/
.confirm {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.14);
}
.btnContainer {
padding: 0 70px;
}
.confirm-wrapper{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999;
box-shadow: 0px 0px 80px 3px rgba(0, 0, 0, 0.2);
}
.confirm-content{
overflow: hidden;
width: 600px;
border-radius: 13px;
background: white
}
.confirm-content p {
display: block;
padding-left: 40px;
}
/*.confirm-content {*/
/* border-radius: 8px;*/
/* box-shadow: 0px 0px 80px 3px rgba(0, 0, 0, 0.2);*/
/* position: absolute;*/
/* top: 50%;*/
/* left: 50%;*/
/* transform: translate(-50%, -50%);*/
/* !*p標(biāo)簽的margin top影響到了父元素 bfc*!*/
/* !*overflow: hidden;*!*/
/* background-color: white;*/
/*}*/
.confirm-content button {
border: 1px solid cornflowerblue;
background-color: transparent;
padding: 25px 50px;
margin-bottom: 30px;
border-radius: 5px;
}
.confirm-fade-enter-active ,.confirm-fade-leave-active{
transition: all .3s;
}
.confirm-fade-enter-from ,.confirm-fade-leave-to{
opacity: 0;
}
.confirm-fade-enter-active .confirm-content {
animation: confirm-zoom-in .3s;
transform-origin: center;
}
.confirm-fade-leave-active .confirm-content {
animation: confirm-zoom-out .3s;
transform-origin: center;
}
@keyframes confirm-zoom-in {
0% {
transform: scale(0);
}
60% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
@keyframes confirm-zoom-out {
0% {
transform: scale(1);
}
30% {
transform: scale(0.4);
}
100% {
transform: scale(0);
}
}
</style>
</html>
布局
修改版
布局

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue3</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="hello-vue" class="box">
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<div>我是父組件</div>
<button @click="handleClick">點(diǎn)我顯示子組件</button>
<cpn ref="compRef" @show-confirm="showConfirm"></cpn>
<confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="確定退出嗎"></confirm>
</div>
<!--點(diǎn)擊按鈕后顯示的那個(gè)組件-->
<template id="mycpn">
<teleport to="body">
<transition name="list-fade">
<div class="cpnContainer" v-show="isshow" @click.stop="handleClose()">
<div class="inner-wrapper" @click.stop>
用到了transition
<div class="text">
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
<div>我是inner-text</div>
</div>
<div class="close" @click="handleClose()">close</div>
</div>
</div>
</transition>
</teleport>
</template>
<!--確認(rèn)關(guān)閉confirm組件-->
<template id="confirm">
<teleport to="body">
<transition name="confirm-fade">
<div v-show="isshow" class="confirm">
<div class="confirm-wrapper">
<div class="confirm-content">
<p>{{text}}</p>
<div class="btnContainer">
<button style="background-color: darkseagreen;margin-right: 40px" @click="confirm">{{confirmBtnText}}</button>
<button @click="cancel">{{cancelBtnText}}</button>
</div>
</div>
</div>
</div>
</transition>
</teleport>
</template>
<script>
const cpn = {
template: "#mycpn",
props: {},
data() {
return {
// bbb: 145612
isshow: false
}
},
methods: {
show() {
this.isshow = true
},
hide() {
// console.log("hide")
this.isshow = false
},
handleClose() {
// console.log("hide")
this.$emit("show-confirm")
},
}
}
const confirm = {
template: "#confirm",
props: {
text: {
type: String,
default: 'fdsafdasfdas'
},
confirmBtnText: {
type: String,
default: '確定'
},
cancelBtnText: {
type: String,
default: '取消'
}
},
data() {
return {
// bbb: 145612
isshow: false
}
},
methods: {
show() {
this.isshow = true
},
hide() {
this.isshow = false
// 控制子組件的顯示
},
// 點(diǎn)擊按鈕后向父組件派發(fā)事件
confirm() {
this.hide();
this.$emit("confirm")
},
cancel() {
this.hide()
this.$emit('cancel')
}
}
}
const HelloVueApp = Vue.createApp({
data() {
return {
message: 'Hello Vue!!'
}
},
components: {
cpn,
confirm
},
methods: {
handleClick() {
// 父組件調(diào)用子組件的方法
// this.$refs.compRef.show()
this.$refs.compRef.show()
},
showConfirm() {
console.log("fdsa")
this.$refs.confirmRef.show()
},
// 點(diǎn)擊取消或確定以后的邏輯
handleConfirm() {
this.$refs.compRef.hide()
},
handleCancel() {
}
}
}).mount("#hello-vue")
</script>
</body>
<style>
* {
font-size: 50px;
}
/*vue內(nèi)置transition*/
.list-fade-enter-active, .list-fade-leave-active {
transition: opacity .3s;
}
.list-fade-enter-active .inner-wrapper, .list-fade-leave-active .inner-wrapper {
transition: all .3s;
}
.list-fade-enter-from, .list-fade-leave-to {
opacity: 0;
}
.list-fade-enter-from .inner-wrapper, .list-fade-leave-to .inner-wrapper {
transform: translate3d(0, 100%, 0);
}
/*子組件樣式*/
.cpnContainer {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .3);
}
.inner-wrapper {
padding: 70px;
background-color: darkcyan;
position: fixed;
bottom: 0;
width: 100%;
box-sizing: border-box;
}
.close {
position: absolute;
top: 50px;
right: 50px;
}
/*confirm組件樣式*/
.confirm {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.14);
}
.btnContainer {
padding: 0 70px;
}
.confirm-wrapper{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999;
box-shadow: 0px 0px 80px 3px rgba(0, 0, 0, 0.2);
}
.confirm-content{
overflow: hidden;
width: 600px;
border-radius: 13px;
background: white
}
.confirm-content p {
display: block;
padding-left: 40px;
}
/*.confirm-content {*/
/* border-radius: 8px;*/
/* box-shadow: 0px 0px 80px 3px rgba(0, 0, 0, 0.2);*/
/* position: absolute;*/
/* top: 50%;*/
/* left: 50%;*/
/* transform: translate(-50%, -50%);*/
/* !*p標(biāo)簽的margin top影響到了父元素 bfc*!*/
/* !*overflow: hidden;*!*/
/* background-color: white;*/
/*}*/
.confirm-content button {
border: 1px solid cornflowerblue;
background-color: transparent;
padding: 25px 50px;
margin-bottom: 30px;
border-radius: 5px;
}
.confirm-fade-enter-active ,.confirm-fade-leave-active{
transition: all .3s;
}
.confirm-fade-enter-from ,.confirm-fade-leave-to{
opacity: 0;
}
.confirm-fade-enter-active .confirm-content {
animation: confirm-zoom-in .3s;
transform-origin: center;
}
.confirm-fade-leave-active .confirm-content {
animation: confirm-zoom-out .3s;
transform-origin: center;
}
@keyframes confirm-zoom-in {
0% {
transform: scale(0);
}
60% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
@keyframes confirm-zoom-out {
0% {
transform: scale(1);
}
30% {
transform: scale(0.4);
}
100% {
transform: scale(0);
}
}
</style>
</html>
案例用到的知識(shí)
父組件如何調(diào)用子組件方法 用ref拿到組件 調(diào)用組件里的方法就ok
關(guān)于事件阻止冒泡
子組件向父組件通信 派發(fā)事件(emit)
boxshadow
vue transition動(dòng)畫
疑問 confirm-zoom動(dòng)畫為什么不能放在container上 只能放在content上
到此這篇關(guān)于vue3 teleport的使用demo的文章就介紹到這了,更多相關(guān)vue3 teleport使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
修改el-form-item中的label里面的字體邊距或者大小問題
這篇文章主要介紹了修改el-form-item中的label里面的字體邊距或者大小問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
web前端Vue報(bào)錯(cuò):Uncaught?(in?promise)?TypeError:Cannot?read?
這篇文章主要給大家介紹了關(guān)于web前端Vue報(bào)錯(cuò):Uncaught?(in?promise)?TypeError:Cannot?read?properties?of?nu的解決方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01
Vue入門之?dāng)?shù)據(jù)綁定(小結(jié))
本篇文章主要介紹了探索Vue高階組件的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
Vue循環(huán)遍歷選項(xiàng)賦值到對(duì)應(yīng)控件的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue-循環(huán)遍歷選項(xiàng)賦值到對(duì)應(yīng)控件的實(shí)現(xiàn)方法啊,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
vue中el-autocomplete支持分頁(yè)上拉加載功能
最近在項(xiàng)目中使用了ElementUI的el-autocomplete,下面這篇文章主要介紹了vue中el-autocomplete支持分頁(yè)上拉加載功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11
優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟
這篇文章主要介紹了優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
vue router-view的嵌套顯示實(shí)現(xiàn)
本文主要介紹了vue router-view嵌套顯示,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
SyntaxError:?/xx.vue:?Unexpected?token,?expected?“,“錯(cuò)誤解
這篇文章主要為大家介紹了SyntaxError:?/xx.vue:?Unexpected?token,?expected?“,“錯(cuò)誤解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
vue3的ref,computed,reactive和toRefs你都了解嗎
這篇文章主要為大家詳細(xì)介紹了vue3的ref,computed,reactive和toRefs,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03

