背景

在公司低代码大屏开发过程中,有一个需求是在一个大屏中可以点按钮打开另一个嵌入的大屏,一开始的效果是页面加载后两个大屏的资源同时加载,会因为资源加载多和慢导致页面渲染也会有些慢,所以这里使用了声明式弹窗组件封装了大屏壳子,使得每一个大屏都可以通过函数创建和销毁。

思路

首先我们需要一个通用的方法可以去创建弹窗、展示弹窗、销毁弹窗,然后外部调用这个方法传入大屏壳子组件和一些prop参数及实践,最后调用这个方法。

参考 https://juejin.cn/post/7251065062131253309#heading-5

代码实现

  1. 先封装一个通用的弹窗钩子函数

// usePopup.js
import { createApp } from 'vue';

const createEl = () => {
    const el = document.createElement('div');
    el.setAttribute(
        'style',
        `
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 2000;
        height: 100%;
        background-color: var( -- el-overlay-color-lighter);
        overflow: auto;
        `,
    );
    return el;
};

export const usePopup = (container) => {
    const el = createEl();
    let app;

    const createMyApp = () => createApp(container);

    const show = () => {
        app = createMyApp();
        app.mount(el);
        document.body.appendChild(el);
    };

    const destroy = () => {
        if (app) app.unmount();
        document.body.removeChild(el);
    };
    return {
        show,
        destroy,
    };
};
  1. 根据业务逻辑封装大屏弹窗方法

// useNestedPage.js
import { h } from 'vue';
import NestedPage from './index.vue';
import { usePopup } from '../../../utils/usePopup';

export const useNestedPage = () => {
    let nestedPageInstance;

    const close = () => {
        nestedPageInstance.destroy();
    };

    const show = (options) => {
        nestedPageInstance = usePopup(
            h(NestedPage, {
                ...options,
                onClose: () => {
                    close();
                },
            }),
        );
        nestedPageInstance.show();
    };
    return {
        show,
        close,
    };
};
  1. 声明式弹窗使用

const { show } = useNestedPage() 

// options为一系列弹窗内展示组件及NestedPage组件的props参数 
show(options)