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

Configure Java development environment in Ubuntu 20.04 LTS

Download the Java Development Kit jdk The downloa...

Zabbix implements monitoring of multiple mysql processes

Three MySQL instance processes are started on one...

(MariaDB) Comprehensive explanation of MySQL data types and storage mechanisms

1.1 Data Type Overview The data type is a field c...

How to solve the error of connecting to the database when ServerManager starts

Servermanager startup connection database error R...

Detailed instructions for installing mysql5.7 database under centos7.2

The mysql on the server is installed with version...

How to connect Navicat to the docker database on the server

Start the mysql container in docekr Use command: ...

Mybatis paging plug-in pageHelper detailed explanation and simple example

Mybatis paging plug-in pageHelper detailed explan...

Web Design Tutorial (6): Keep your passion for design

<br />Previous article: Web Design Tutorial ...

Docker swarm simple tutorial

swarm three virtual machines 132,133,134 1. Initi...

Detailed description of the function of new in JS

Table of contents 1. Example 2. Create 100 soldie...

Detailed explanation of Nginx rewrite jump application scenarios

Application scenario 1: Domain name-based redirec...

Example code for configuring monitoring items and aggregated graphics in Zabbix

1. Install Zabbix Agent to monitor the local mach...