'How to create a global modal to show message when needed in any component in Vue3?

I want to create a global component to show error message or info message in Vue 3, like Alert or Comfirm Modal.

In Vue2, I can do this, create a plugin like this:

import AlertComponent from "./Alert.vue";

const Alert = {};

Alert.install = (Vue) => {
    const AlertConstructor = Vue.extend(AlertComponent);
    const instance = new AlertConstructor();
    instance.$mount(document.createElement("div"));

    Vue.prototype.$alert = (msg) => {
        document.body.appendChild(instance.$el);
        // alert logic
        instance.type = "alert";
        instance.msg = msg;
        instance.isShow = true;
        instance.instance = instance;
    };

    Vue.prototype.$confirm = (msg, success, cancel) => {
        document.body.appendChild(instance.$el);
        // confirm logic
        instance.type = "confirm";
        instance.msg = msg;
        instance.isShow = true;
        instance.instance = instance;
        if (typeof success !== "undefined") {
            instance.success = success;
        }
        if (typeof cancel !== "undefined") {
            instance.cancel = cancel;
        }
    };
};

export default Alert;

which I can import it in main.js:

import Alert from './components/modules/alert'

Vue.use(Alert)

And use it in any component like this:

this.$alert('xxxxx message')

// or

this.$confirm('xxxx', () => {})

Question:

How to create a such function/component in Vue3?



Solution 1:[1]

In 3.x the app instance is created trough createApp so you don't need Vue constructor:


import AlertComponent from './Alert.vue'

const Alert = {}

Alert.install = (app) => {
  const AlertConstructor ={extend:AlertComponent}
  const instance = new AlertConstructor()
  instance.$mount(document.createElement('div'))

  app.config.globalProperties.$alert = (msg) => {
    document.body.appendChild(instance.$el)
    // alert logic
    instance.type = 'alert'
    instance.msg = msg
    instance.isShow = true
    instance.instance = instance
  }

  app.config.globalProperties.$confirm = (msg, success, cancel) => {
    document.body.appendChild(instance.$el)
    // confirm logic
    instance.type = 'confirm'
    instance.msg = msg
    instance.isShow = true
    instance.instance = instance
    if (typeof success !== 'undefined') {
      instance.success = success
    }
    if (typeof cancel !== 'undefined') {
      instance.cancel = cancel
    }
  }
}

export default Alert

then import it in main.js like :

import Alert from './components/modules/alert'
const app = createApp(App);

app.use(Alert);

Solution 2:[2]

Use createApp to render the component in Vue 3:

// components/modules/alert/alert.js
import { createApp } from 'vue'
import AlertComponent from './Alert.vue'

const Alert = {}

Alert.install = (app) => {
  const instance = createApp(AlertComponent).mount(document.createElement('div'))

  app.config.globalProperties.$alert = (msg) => {
    document.body.appendChild(instance.$el)
    // alert logic
    instance.type = 'alert'
    instance.msg = msg
    instance.isShow = true
    instance.instance = instance
  }

  app.config.globalProperties.$confirm = (msg, success, cancel) => {
    document.body.appendChild(instance.$el)
    // confirm logic
    instance.type = 'confirm'
    instance.msg = msg
    instance.isShow = true
    instance.instance = instance
    if (typeof success !== 'undefined') {
      instance.success = success
    }
    if (typeof cancel !== 'undefined') {
      instance.cancel = cancel
    }
  }
}
// main.js
import Alert from './components/modules/alert'
const app = createApp(App);

app.use(Alert);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2