一个Vue弹窗小工具

281 阅读1分钟

使用场景

弹窗在业务中经常会用到,Vue中,我们要实现一个复杂弹窗,通常需要三步:

  1. 定义弹窗文件,写出弹窗的样式;
  2. 在页面中引入弹窗组件;
  3. 通过visible属性来控制弹窗的显示和隐藏;

这种方式比较基础,也比较繁琐。试想一下,如果我们多个页面都需要这个弹窗,这时候就会有很多冗余的代码。而这个小工具类,就是为了让我们像alert一样的丝滑的使用弹窗。

实现

因为弹窗大致可以分为两类:confirm/alert.

  • Confirm 弹窗有两种状态:sure/cancel
  • Alert 弹窗只有一种状态:sure

因此,我们可以用Promise的方式来调用我们的弹窗。

// confirm dialog
myConfirm.show(opts).then(res => {
  // click sure button
}).catch(err => {
  // click cancel button
});
// alert dialog
myAlert.show(opts).then(res => {
  // close alert dialog.
});

当然,这里如果有超过两种状态的弹窗,也可以通过resolve函数传入不同的状态值来实现。

工具类实现:

import Vue from 'vue'

class DialogService {
  instance = null
  Comp = null
  vueOpts = null
  constructor(Comp, vueOpts) {
    this.Comp = Comp
    this.vueOpts = vueOpts || {}
  }
  __initDialog(Comp) {
    const CompVue = Vue.extend(Comp)
    this.instance = new CompVue({
      el: document.createElement('div'),
      ...this.vueOpts,
    })
    document.body.appendChild(this.instance.$el)
  }
  __destroyDialog() {
    document.body.removeChild(this.instance.$el)
    this.instance = null
  }
  show(options) {
    this.__initDialog(this.Comp)
    return new Promise((resolve, reject) => {
      this.instance.show(options)
      const _resolve = this.instance.resolve.bind(this)
      const _reject = this.instance.reject.bind(this)
      this.instance.resolve = async res => {
        const _res = await _resolve(res)
        resolve(_res)
        this.__destroyDialog()
      }
      this.instance.reject = async res => {
        const _res = await _reject(res)
        reject(_res)
        this.__destroyDialog()
      }
    })
  }
}

export const dialogServiceMixins = {
  data() {
    return {
      visible: false
    }
  },
  methods: {
    show() {
      this.visible = true;
    },
    resolve() {},
    reject() {}
  }
}

export default DialogService

如何调用:

import DialogService from './DialogService';
import ConfirmDialogComp from './ConfirmDialog';

const confirmDialog = new DialogService(ConfirmDialog);

confirmDialog.show();