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)
Preface: Today I want to remotely connect to MySQ...
Linux and Unix are multi-user operating systems, ...
Table of contents Preface 1. GMT What is GMT Hist...
Simply put, distinct is used to remove duplicates...
background: Sometimes we need to display json dat...
I hope to implement some properties of the query ...
1. golang:latest base image mkdir gotest touch ma...
If you want the application service in the Docker...
Table of contents 1. Content Overview 2. Concepts...
When developing mobile apps, you often encounter ...
Three Paradigms 1NF: Fields are inseparable; 2NF:...
Effect: <!doctype html> <html> <he...
Today, when developing, I encountered a method wh...
Table of contents 1.1. Enable MySQL binlog 1.2. C...
When we display long text, we often need to interc...