1、首先创建一个普通的弹窗组件,放到页面中测试下是否能实现组件加载完毕后弹窗

注意: 用 transition 组件的时候,如果子元素做不同的动画,enter-active 和 leave-active 的动画时长需要与子元素动画时长最长的时间相等,不然会比较短会提前结束子元素动画,过长会导致子元素动画做完之后,蒙版产生遮挡

<script setup lang="ts">
import { onMounted, ref } from "vue";
const show = ref<boolean>(false);

const props = defineProps<{
  removeNode: Function;
}>();

onMounted(() => {
  // 页面挂在后开始做动画
  show.value = true;
});
const close = () => {
  if (show.value) {
    //加这层判断主要为了防止用户频繁点击蒙版

    //动画结束后关闭弹窗
    show.value = false;
    setTimeout(() => {
      // 动画结束后移除元素
      props.removeNode();
    }, 500);
  }
};
</script>

<template>
  <div class="">
    <transition name="pop">
      <div class="pop-wrap" v-if="show">
        <div class="mask" @click="close"></div>
        <div class="pop-content">
          <div class="title">弹窗组件</div>
          <div class="content">
            <slot></slot>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<style scoped>
.pop-wrap {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}
.mask {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
  transition: all 0.5s;
}
.pop-enter-active,
.pop-leave-active {
  /* 时长需要与各个子元素(maske、pop-content)动画时长最长的相等 */
  transition: all 0.5s;
}
.pop-enter-from .mask,
.pop-leave-to .mask {
  opacity: 0;
}
.pop-enter-to .mask,
.pop-leave-from .mask {
  opacity: 1;
}
.pop-enter-from .pop-content,
.pop-leave-to .pop-content {
  opacity: 0;
  transform: translate(-50%, -70%);
}
.pop-enter-to .pop-content,
.pop-leave-from .pop-content {
  opacity: 1;
  transform: translate(-50%, -50%);
}
.pop-content {
  background: #fff;
  border-radius: 10px;
  width: 50%;
  height: 40%;
  padding: 10px;
  position: absolute;
  left: 50%;
  top: 50%;
  transition: all 0.5s;
  transform: translate(-50%, -50%);
}
.title {
  height: 50px;
  font-size: 20px;
  color: #333;
  font-weight: bold;
  line-height: 50px;
  border-bottom: 1px solid #999;
}
</style>


2.在popup同级目录下创建一个index.ts 去渲染component

import { createApp, h } from "vue"
import Popup from './popup.vue'


export default function popup(vnNode: any) {
    const parentNode = document.createElement('div')
    const popupInstance = createApp({
        render() {
            return h(
                Popup,
                {
                    //popup的属性
                    removeNode: () => {
                        // 销毁弹窗组件
                        document.body.removeChild(parentNode)

                    }
                },
                // children
                [
                    h(vnNode)
                ]
            )
        }
    })


    document.body.appendChild(parentNode)
    popupInstance.mount(parentNode)
}

3.调用

<script setup lang="ts">
import createPopup from "./components/popup";
import PopupContent from './components/popConnt.vue'// 放入插槽的弹窗内容

const createComponent = ()=>{
  createPopup(PopupContent)
}
</script>

<template>
<button @click="createComponent">创建组件</button>
</template>

Logo

前往低代码交流专区

更多推荐