乐趣区

关于前端:Vue3第8课Vue3中的teleport组件瞬间移动组件的使用

对于 teleport 组件,咱们先来看一下官网是怎么说的吧。

Teleport 提供了一种洁净的办法,容许咱们管制在 DOM 中哪个父节点下渲染了 HTML,而不用求助于全局状态或将其拆分为两个组件。
简略的来说就是 teleport 能够管制在哪一个 dom 下来渲染你的组件,去解决一些应用组件时受到父元素款式影响的问题。

间接来看一个例子吧。咱们写一个 modal 弹窗的组件。点击按钮使其呈现,再次点击使其敞开。

Modal.vue

<template>
  <div id="modal">
    <h2> 这是一个 modal</h2>
  </div>
</template>
<script lang="ts">
export default {};
</script>
<style>
#modal {
  width: 200px;
  height: 200px;
  border: 2px solid black;
  background: white;
  position: fixed;
  left: 50%;
  top: 50%;
  margin-left: -100px;
  margin-top: -100px;
}
</style>

TeleportCom.vue

<template>
  <div class="teleport-com">
    <button @click="showModal">{{show ? "暗藏" : "显示"}}</button>
    <Modal v-if="show" />
  </div>
</template>

<script lang="ts">
import {defineComponent, reactive, toRefs} from "vue";
import Modal from "@/components/Modal.vue";
export default defineComponent({
  name: "teleport-com",
  components: {Modal,},
  setup() {
    const data = reactive({
      show: false,
      showModal: () => {data.show = !data.show;},
    });
    const refData = toRefs(data);
    return {...refData,};
  },
});
</script>
<style lang="scss" scoped>
.teleport-com {
}
</style>

来看一下成果

会发现没有在 Modal.vue 组件写文字居中,然而文字居中了。这是因为 Modal 组件渲染在了 app 节点中,受到了 app 节点款式的影响。

咱们怎么在不批改 Modal 组件上的前提上解决这个问题了,teleport提供了解决方案。

  1. 批改 index.html,新增一个 id 为modal-container 的 div
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    // 新增一个 id 为 modal-container 的 div
    <div id="modal-container"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
  1. 批改 Modal.vue 组件, 应用 teleport 组件包裹
    <template>
    // 应用 teleport 组件包裹
    <teleport to=”#modal-container”>
    <div id=”modal”>
    <h2> 这是一个 modal</h2>
    </div>
    </teleport>
    </template>
    <script lang=”ts”>
    export default {};
    </script>
    <style>

    modal {

    width: 200px;
    height: 200px;
    border: 2px solid black;
    background: white;
    position: fixed;
    left: 50%;
    top: 50%;
    margin-left: -100px;
    margin-top: -100px;
    }
    </style>

查看成果,款式不受到 app 节点管制,且不在渲染在 app 节点中

  1. 或者咱们还能这样改,重用性更强。把 Modal.vue 还原为文章最后的样子,批改 TeleportCom.vue, 应用teleport 间接包裹应用的组件
<template>
  <div class="teleport-com">
    <button @click="showModal">{{show ? "暗藏" : "显示"}}</button>
    // 应用 `teleport` 间接包裹应用的组件
    <teleport to="#modal-container">
      <Modal v-if="show" />
    </teleport>
  </div>
</template>

<script lang="ts">
import {defineComponent, reactive, toRefs} from "vue";
import Modal from "@/components/Modal.vue";
export default defineComponent({
  name: "teleport-com",
  components: {Modal,},
  setup() {
    const data = reactive({
      show: false,
      showModal: () => {data.show = !data.show;},
    });
    const refData = toRefs(data);
    return {...refData,};
  },
});
</script>
<style lang="scss" scoped>
.teleport-com {
}
</style>

能够看到也是一样的成果哟

退出移动版