preface

In the ERA of VUe2.0, we often have the need to write code logic to write components under a template, because we can use the internal state data of components to control the presentation of components. But technically we want to move this code somewhere in the DOM outside of the Vue app.

For a simple example, when we use a Modal component, we put it in our template template, but since the Modal component wants to be at the top of the page, it’s best to control when we mount the Modal component on top of the body, We can use zIndex to control the location of modal very well, but it’s not so easy when it’s nested in the templat.

Implementation in VUe2.0

In VUe2.0, WHEN I write this component, I manually mount it. I wrote a VUE directive to do this operation, which helps me mount the Modal component to the body, which can also control the modal presentation by controlling zIndex.

function insert(el) {
  const parent = el.parentNode;
  if(parent && parent ! = =document.body) {
      parent.removeChild(el);
      document.body.appendChild(el); }}export default (typeof window! = ='undefined' ? {
  inserted(el, { value }) {
      if(value) { insert(el); }},componentUpdated(el, { value }) {
      if(value) { insert(el); }},} : {});Copy the code

In fact, the above code is simple to remove modal from his original mounted parent node, and then mount to the body, through manual form to mount again, can very good to solve this problem, of course, the above is just a simple logic, if you need to consider unloading and other logic code must be added.

<template>
  <div class="modal" v-to-body="show" v-if="show">
    <div class="modal-mask" @click="close"></div>
    <slot></slot>
  </div>
</template>

<script>
import "./style.scss";
import toBody from ".. /directives/to-body";
export default {
  props: {
    show: Boolean,},directives: {
    toBody,
  },
  methods: {
    close() {
      this.$emit("close"); ,}}};</script>
Copy the code

To be honest, the implementation in VUe2.0 was fine, just not very elegant and required extra code control, so vue3.0 brought Teleport- any portal directly

See Vue2.0-Modal for the code

What is a Teleport

Teleport can directly help us render components anywhere on the back page, as long as we specify the target object for rendering. Teleport is very simple to use.

<template>
  <teleport to="body" class="modal" v-if="show">
    <div class="modal-mask" @click="close"></div>
    <slot></slot>
  </teleport>
</template>

<script>
import "./style.scss";
export default {
  props: {
    show: Boolean,},methods: {
    close() {
      this.$emit("close"); ,}}};</script>
Copy the code

With the above code, we can easily implement what vue2.0 did before.

See Vue3.0-Modal for the code

Pay attention to the point

Use with Vue Components

In this case, even if the Child-Component is rendered in a different place, it will still be a child of parent-Component and will receive a Name prop from it.

This also means that the injection from the parent component works as expected, and that the child component is nested beneath the parent component in Vue Devtools, rather than where the actual content is moved to.

const app = Vue.createApp({
  template: ` 

Root instance

`
}) app.component('parent-component', { template: `

This is a parent component

`
}) app.component('child-component', { props: ['name'].template: `
Hello, {{ name }}
`
}) Copy the code
Use multiple teleports on the same target

What happens when we send multiple teleports to the same location?

<teleport to="#modals">
  <div>A</div>
</teleport>
<teleport to="#modals">
  <div>B</div>
</teleport><! -- result--><div id="modals">
  <div>A</div>
  <div>B</div>
</div>
Copy the code

We can see that in this case, multiple Teleport components can mount their content to the same target element. The order will be a simple append — the later mount will follow the earlier mount in the target element.

conclusion

To describe Teleport in one sentence is to keep the code organization logic in the component, so that we can use the data state inside the component to control the presentation of the component, but the final rendering place can be arbitrary, not limited to the component itself