Vue2 中基于Promise封装dialogManager,优雅的使用dialog

320 阅读1分钟

注意:代码来自我浩总

DialogManager.js

import Vue from "vue";
import { i18n } from "../main";

export default class DialogManager {
    static dialogs = new Set();

    static openDialog = (component, props) => {
        return new Promise((resolve, reject) => {
            const DialogConstructor = createDialogConstructor(component);
            const dialogInstance = initDialogInstance(DialogConstructor, {
                myProps: props,
                resolve: data => resolve({ dialogInstance, data }),
                reject: data => reject({ dialogInstance, data })
            });
            dialogInstanceMount(dialogInstance);
            this.dialogs.add(dialogInstance);
        });
    };

    static closeDialog = dialogInstance => {
        dialogInstanceUnmount(dialogInstance);
        this.dialogs.delete(dialogInstance);
        dialogInstance.$destroy();
    };

    static hasDialog = dialogInstance => {
        return this.dialogs.has(dialogInstance);
    };
}

function createDialogConstructor(component) {
    return Vue.extend(component);
}

function initDialogInstance(DialogConstructor, props) {
    return new DialogConstructor({
        el: document.createElement("div"),
        propsData: props,
        i18n
    });
}

function dialogInstanceMount(dialogInstance) {
    document.body.appendChild(dialogInstance.$el);
    Vue.nextTick(() => {
        dialogInstance.visible = true;
    });
}

function dialogInstanceUnmount(dialogInstance) {
    dialogInstance.visible = false;
    document.body.removeChild(dialogInstance.$el);
}

页面中使用:

deleteListItem(task) {
            // 删除任务
            // console.log(task);
            DialogManager.openDialog(DeleteTrainTask, {
                task
            }).then(data => {
                    // 点击确定按钮后刷新表格
                    this.getAlgoList();
                    this.shouldRefresh = false;
                    this.$nextTick(() => {
                        this.shouldRefresh = true;
                    });
                    DialogManager.closeDialog(data.dialogInstance);
                }).catch(data => {
                    console.log(data);
                });
        },

弹窗:

<template>
    <Dialog :dialog-visible="visible" title="" @comfirm="dialogConfirm" @cancel="dialogCancel">
        <div class="delete-dataset-dialog">
            <wb-icon icon="public-state-warning" class="warning-ico" />
            <div class="text">
                <h3>确定要删除该训练任务吗?</h3>
                <p>任务删除后,相关配置会全部清除,请谨慎操作。</p>
            </div>
        </div>
    </Dialog>
</template>

<script>
import Dialog from "../../dialog/Dialog.vue";
import { AlgoDevelopAPI } from "../../../apis/ai/index";
export default {
    name: "StartManualAnnotationDialog",
    methods: {
        async dialogConfirm() {
            // console.log(this.myProps);
            let id = this.myProps.task.trainingId;
            await AlgoDevelopAPI.deleteTrainingTask(id).then(res => {
                if (res.code === 0) {
                    this.$message({
                        type: "success",
                        showClose: true,
                        duration: 5000,
                        message: "删除成功",
                        offset: 80
                    });
                } else {
                    this.$message({
                        type: "warning",
                        showClose: true,
                        duration: 5000,
                        message: res.msg,
                        offset: 80
                    });
                }
            });
            this.resolve("confirm");
        },
        dialogCancel() {
            this.visible = false;
            this.reject("cancel");
        }
    },
    data() {
        return {
            formInfo: {
                name: "",
                desc: ""
            }
        };
    },
    components: {
        Dialog
    },
    props: {
        myProps: {
            type: Object,
            default: null
        },
        resolve: {
            type: Function,
            default: null
        },
        reject: {
            type: Function,
            default: null
        },
        visible: {
            type: Boolean,
            default: false
        }
    }
};
</script>

<style lang="scss">
.delete-dataset-dialog {
    // width: 435px;
    overflow: hidden;
    .warning-ico {
        float: left;
        margin-right: 10px;
        width: 20px !important;
        height: 20px !important;
        margin-top: 3px;
    }
    .text {
        float: left;
        h3 {
            margin-bottom: 12px;
            height: 26px;
            font-size: 18px;
            font-family: PingFangSC-Semibold, PingFang SC;
            font-weight: 600;
            color: #2b2b33;
            line-height: 26px;
        }
    }
    p {
        height: 22px;
        font-size: 14px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #4b4b55;
        line-height: 22px;
    }
}
</style>

Dialog组件:

<template>
    <el-dialog
        title="提示"
        :visible.sync="dialogVisible"
        :width="width"
        :close-on-click-modal="false"
        custom-class="wb-dialog"
        ref="dialog"
        :before-close="cancel"
        :show-close="showClose"
    >
        <!-- 标题 -->
        <div class="wb-dialog-title" slot="title">{{ title }}</div>
        <!-- 自定义内容 -->
        <div class="wb-dialog-body">
            <slot />
        </div>
        <!-- 底部操作 -->
        <span slot="footer" class="wb-dialog-footer" v-if="showFooter">
            <el-button @click="cancel">{{ cancelText }}</el-button>
            <el-button type="primary" @click="comfirm" disabled v-if="isDisabled">
                {{ comfirmText }}
            </el-button>
            <el-button type="primary" @click="comfirm" v-else :disabled="comfirmDisabled">{{ comfirmText }}</el-button>
        </span>
    </el-dialog>
</template>
<script>
import Dialog from "./Dialog";
export default Dialog;
</script>
export default {
    data() {
        return {};
    },
    props: {
        dialogVisible: {
            type: Boolean,
            default: false
        },
        title: {
            type: String,
            default: "标题"
        },
        cancelText: {
            type: String,
            default: "取 消"
        },
        comfirmText: {
            type: String,
            default: "确 定"
        },
        showFooter: {
            type: Boolean,
            default: true
        },
        isDisabled: {
            type: Boolean,
            default: false
        },
        comfirmDisabled: {
            type: Boolean,
            default: false
        },
        width: {
            type: String,
            default: "30%"
        },
        showClose: {
            type: Boolean,
            default: true
        }
    },
    methods: {
        comfirm() {
            this.$emit("comfirm");
        },
        cancel() {
            this.$emit("cancel");
        }
    }
};