vue3 新组件之 Teleport,解决组件间 css 层级问题

最近在用 vue3 写一个小 ui 库,其中 dialog 组件的弹出框,涉及到了组件层级,也就是 z-index 的问题,下面我们来代码演示一下

首先是组件 html 部分的代码:

<template>
<template v-if="visible">
  <!-- 遮罩层,z-index 为 10 -->
  <div class="aha-dialog-overlay" @click="onClickOverlay"></div>
  <!-- dialog 容器,z-index 为 11 -->
  <div class="aha-dialog-wrapper">
    <div class="aha-dialog">
      <header>
        <slot name="title"></slot><span @click="close" class="aha-dialog-close"></span>
      </header>
      <main>
        <slot name="content"></slot>
      </main>
      <footer>
        <Button level="main" @click="ok">OK</Button>
        <Button @click="cancel">Cancel</Button>
      </footer>
    </div>
  </div>
</template>
</template>

在父组件中引入 dialog 组件,效果如下:

 

 目前来看是没什么问题的,那如果父组件中有一个层级高的标签呢?我在父组件写了两个容器,其中一个 z-index 为 1,里面包含了 dialog 组件,另一个 z-index 为 2,如下:

<template>
<div>Dialog 示例</div>
<h1>示例1</h1>
<!-- z-index 为 1 的父容器,里面包含了 dialog 组件-->
<div style="position: relative; z-index: 1">
  <Button @click="toggle">toggle</Button>
  <Dialog v-model:visible="x" :ok="f1" :cancel="f2">
    <template v-slot:title>
      <strong>加粗的标题</strong>
    </template>
    <template v-slot:content><strong>hi</strong></template>
  </Dialog>
</div>
<!-- 层级高的标签,z-index 为 2 -->
<div style="
      position: relative;
      z-index: 2;
      width: 300px;
      height: 300px;
      background: red;
    "></div>
</template>

效果如下:

 

 下面我们触发 dialog 显示事件:

 

 可以看到 dialog 被挡在了红色方块的下面,因为元素在 html 中的层级是受父元素限制的,虽然我们给 dialog 设置了 z-index 为 11,但在父元素 z-index 为 1 的情况下,就算你给子元素设为 1000,他在页面中的层级也会比 z-index:2 要小。

vue3 新推出的组件 Teleport 就可以解决这个问题,让子组件不以父组件为层级参照,直接传送到 body 或者 其他元素下面

我们现在用 Teleport 标签把我们 dialog 组件需要提升层级的遮罩层 overlay 和弹出层 dialog 包裹起来:

 

 再看一下效果:

 

 ok,完美解决~

posted @ 2020-09-24 16:08  小船二  阅读(1301)  评论(0编辑  收藏  举报