Official Websitehttps://cli.vuejs.org/en/guide/ Sometimes there's a part of a component's template that logically belongs in that component, but from a technical perspective it's better to move that part of the template to another location in the DOM outside of the Vue app. CaseBoth components are in the parent element and are children of the parent component, but from a technical point of view, they should be mounted under the body Unmodified version <!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>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <button @click="handleClick">Click me to show subcomponents</button> <cpn ref="compRef" @show-confirm="showConfirm"></cpn> <confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="Are you sure you want to exit?"></confirm> </div> <!--The component displayed after clicking the button--> <template id="mycpn"> <transition name="list-fade"> <div class="cpnContainer" v-show="isshow" @click.stop="handleClose()"> <div class="inner-wrapper" @click.stop> Using transition <div class="text"> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> </div> <div class="close" @click="handleClose()">close</div> </div> </div> </transition> </template> <!--Confirm to close the confirm component--> <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: 'OK' }, cancelBtnText: { type: String, default: 'Cancel' } }, data() { return { // bbb: 145612 isshow: false } }, methods: { show() { this.isshow = true }, hide() { this.isshow = false //Control the display of subcomponents}, // After clicking the button, dispatch the event confirm() to the parent component { 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() { // The parent component calls the child component's method // this.$refs.compRef.show() this.$refs.compRef.show() }, showConfirm() { console.log("fdsa") this.$refs.confirmRef.show() }, // Click Cancel or Confirm to execute the following logic handleConfirm() { this.$refs.compRef.hide() }, handleCancel() { } } }).mount("#hello-vue") </script> </body> <style> * { font-size: 50px; } /*vue built-in 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); } /*Subcomponent style*/ .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 component style*/ .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%);*/ /* !*The margin top of the p tag affects the parent element 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> layout Modified version layout <!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>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <div>I am the parent component</div> <button @click="handleClick">Click me to show subcomponents</button> <cpn ref="compRef" @show-confirm="showConfirm"></cpn> <confirm ref="confirmRef" @confirm="handleConfirm" @cancel="handleCancel" text="Are you sure you want to exit?"></confirm> </div> <!--The component displayed after clicking the button--> <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> Using transition <div class="text"> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> <div>I am inner-text</div> </div> <div class="close" @click="handleClose()">close</div> </div> </div> </transition> </teleport> </template> <!--Confirm to close the confirm component--> <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: 'OK' }, cancelBtnText: { type: String, default: 'Cancel' } }, data() { return { // bbb: 145612 isshow: false } }, methods: { show() { this.isshow = true }, hide() { this.isshow = false //Control the display of subcomponents}, // After clicking the button, dispatch the event confirm() to the parent component { 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() { // The parent component calls the child component's method // this.$refs.compRef.show() this.$refs.compRef.show() }, showConfirm() { console.log("fdsa") this.$refs.confirmRef.show() }, // Click Cancel or Confirm to execute the following logic handleConfirm() { this.$refs.compRef.hide() }, handleCancel() { } } }).mount("#hello-vue") </script> </body> <style> * { font-size: 50px; } /*vue built-in 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); } /*Subcomponent style*/ .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 component style*/ .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%);*/ /* !*The margin top of the p tag affects the parent element 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> Knowledge used in the case How does the parent component call the child component method? Use ref to get the component and call the method in the component. This is the end of this article about the demo of using vue3 teleport. For more relevant content about using vue3 teleport, please search the previous articles of 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: MySQL EXPLAIN statement usage examples
>>: Basic HTML directory problem (difference between relative path and absolute path)
1. Create a test table CREATE TABLE `mysql_genara...
Table of contents JavaScript events: Commonly use...
Download the MySQL installation package. I downlo...
Table of contents Preface 1. Application componen...
Table of contents Preface: Encryption algorithm: ...
Table of contents 1. Back up the old MySQL5.7 dat...
How to use if in Linux to determine whether a dir...
Table of contents Object parameters using destruc...
MySql Download 1. Open the official website and f...
Phenomenon: After MySQL version 5.7, the default ...
[Abstract] This article quickly builds a complete...
/******************** * Application of linked lis...
Table of contents First, let's talk about the...
I call this kind of bug a typical "Hamlet&qu...
The image of the microservice will be uploaded to...