Detailed use cases of vue3 teleport

Detailed use cases of vue3 teleport

Official Website

https://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.

Case

insert image description here

insert image description here

Both 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
insert image description here

<!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.
About events to prevent bubbling child components from sending events to parent components (emit)
boxshadow
Vue transition animation question: Why can't the confirm-zoom animation be placed on the container but only on the content?

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:
  • Detailed explanation of how to use Teleport, a built-in component of Vue3
  • Detailed explanation of the use of Teleport in Vue3
  • Detailed explanation of how to use the vue3 Teleport instant movement function

<<:  MySQL EXPLAIN statement usage examples

>>:  Basic HTML directory problem (difference between relative path and absolute path)

Recommend

More Features of the JavaScript Console

Table of contents Overview console.log console.in...

IE6 BUG and fix is ​​a preventive strategy

Original article: Ultimate IE6 Cheatsheet: How To...

Solution to the problem of large font size on iPhone devices in wap pages

If you don't want to use javascript control, t...

Analysis of the use of Linux vulnerability scanning tool lynis

Preface: Lynis is a security audit and hardening ...

Windows 2019 Activation Tutorial (Office2019)

A few days ago, I found that the official version...

Use href in html to pop up a file download dialog box when clicking a link

I learned a new trick today. I didn’t know it befo...

Intellij IDEA quick implementation of Docker image deployment method steps

Table of contents 1. Docker enables remote access...

FlashFXP ftp client software registration cracking method

The download address of FlashFXP is: https://www....

Detailed explanation of common methods of JavaScript String

Table of contents 1. charAt grammar parameter ind...

Native javascript+CSS to achieve the effect of carousel

This article uses javascript+CSS to implement the...

A brief discussion on the CSS overflow mechanism

Why do you need to learn CSS overflow mechanism i...

When you enter a URL, what exactly happens in the background?

As a software developer, you must have a complete...

Mysql 5.7.19 free installation version encountered pitfalls (collection)

1. Download the 64-bit zip file from the official...