vue3 teleport的使用案例詳解
官網(wǎng)
https://cli.vuejs.org/zh/guide/
有時組件模板的一部分邏輯上屬于該組件,而從技術(shù)角度來看,最好將模板的這一部分移動到 DOM 中 Vue app 之外的其他位置。
案例
這兩個組件都是在父元素里的,是父組件的子級,但是從技術(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">點我顯示子組件</button> <cpn ref="compRef" @show-confirm="showConfirm"></cpn> <confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="確定退出嗎"></confirm> </div> <!--點擊按鈕后顯示的那個組件--> <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 // 控制子組件的顯示 }, // 點擊按鈕后向父組件派發(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() }, // 點擊取消或確定以后的邏輯 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">點我顯示子組件</button> <cpn ref="compRef" @show-confirm="showConfirm"></cpn> <confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="確定退出嗎"></confirm> </div> <!--點擊按鈕后顯示的那個組件--> <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 // 控制子組件的顯示 }, // 點擊按鈕后向父組件派發(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() }, // 點擊取消或確定以后的邏輯 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>
案例用到的知識
父組件如何調(diào)用子組件方法 用ref拿到組件 調(diào)用組件里的方法就ok
關(guān)于事件阻止冒泡
子組件向父組件通信 派發(fā)事件(emit)
boxshadow
vue transition動畫
疑問 confirm-zoom動畫為什么不能放在container上 只能放在content上
到此這篇關(guān)于vue3 teleport的使用demo的文章就介紹到這了,更多相關(guān)vue3 teleport使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
修改el-form-item中的label里面的字體邊距或者大小問題
這篇文章主要介紹了修改el-form-item中的label里面的字體邊距或者大小問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10web前端Vue報錯:Uncaught?(in?promise)?TypeError:Cannot?read?
這篇文章主要給大家介紹了關(guān)于web前端Vue報錯:Uncaught?(in?promise)?TypeError:Cannot?read?properties?of?nu的解決方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01Vue入門之?dāng)?shù)據(jù)綁定(小結(jié))
本篇文章主要介紹了探索Vue高階組件的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01Vue循環(huán)遍歷選項賦值到對應(yīng)控件的實現(xiàn)方法
這篇文章主要介紹了Vue-循環(huán)遍歷選項賦值到對應(yīng)控件的實現(xiàn)方法啊,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟
這篇文章主要介紹了優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04SyntaxError:?/xx.vue:?Unexpected?token,?expected?“,“錯誤解
這篇文章主要為大家介紹了SyntaxError:?/xx.vue:?Unexpected?token,?expected?“,“錯誤解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08vue3的ref,computed,reactive和toRefs你都了解嗎
這篇文章主要為大家詳細(xì)介紹了vue3的ref,computed,reactive和toRefs,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03