Modal boxes are not new to browsing the web.

But how do you package a VUE component into a reusable modal box during vUE development?

1, the train of thought

First of all, it is not difficult to find that modal boxes have the following characteristics:

  • There is a translucent mask that prevents the user from doing anything else without completing the modal box command
  • The display is on the top layer, which means that many of the modal boxes are placed directlybodyIn the element

I started by thinking, could I define the modal box style in the Vue file and then pass the values using props or slot and call the methods using refs? It turns out that this is not only inconvenient (you have to register the component each time), but it also makes it impossible to place the modal box directly inside the body.

Referring to the official documentation, I found that I should write a matching JS file, define the function to display the modal box in the JS file, use this JS to create an element under the body element, and mount the vue component to it. So let’s just do that.

2. Write vUE files and complete the basic styles of modal boxes

To complete some basic styles for the dialog, I created a vue file in the Components directory, which looks like this:

<template>
  <div class="mydialog">
    <div class="frame">
      <div class="content">
        <img :src="image" />
        <div class="text">{{ text }}</div>
      </div>
      <div class="buttons">
        <div class="ok" @click="clickOk">determine</div>
        <div class="cancel" @click="clickCancel">cancel</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'mydialog'.data() {
    return {
      /** * displays text */
      text: ' './** * display image */
      image: ' './** * The DOM element mounted by the modal box to be used later to destroy the modal box */
      mountDom: ' '}; },methods: {
    /** * Customize the event */
    ok() {},
    /** * Custom cancel event */
    cancel() {},
    clickOk() {
      // Execute the custom determination method first
      this.ok();
      // js passes in elements mounted by the modal box instance and destroys them when closed
      this.mountDom.remove();
    },
    clickCancel() {
      // Execute the custom cancel method first
      this.cancel();
      // js passes in elements mounted by the modal box instance and destroys them when closed
      this.mountDom.remove(); ,}}};</script>

<style lang="scss" scoped>
.mydialog {
  position: absolute;
  width: 100vw;
  height: 100vh;
  left: 0;
  top: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(255.255.255.0.7);

  .frame {
    width: 560px;
    height: 250px;
    background-color: rgb(177.255.229);
    box-shadow: 1px 1px 7px 2px rgb(90.203.255);
    border-radius: 5px;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    align-items: center;

    .content {
      display: flex;
      width: 85%;
      justify-content: flex-start;
      align-items: center;

      img {
        height: 64px;
      }

      .text {
        font-size: 24px;
        margin-left: 24px; }}.buttons {
      display: flex;
      width: 80%;
      justify-content: space-around;
      align-items: center;
      font-size: 26px;

      .ok..cancel {
        width: 75px;
        height: 32px;
        text-align: center;
        line-height: 32px;
        border-radius: 6px;
        user-select: none;
        cursor: pointer;
      }

      .ok{&:hover {
          color: white;
          background-color: blue; }}.cancel{&:hover {
          color: white;
          background-color: rgb(255.0.98);
        }
      }
    }
  }
}
</style>
Copy the code

The point here is that in data() I have defined some variables that we can use to customize the contents of the modal box.

The question is, how can a modal box destroy itself? Even if you close yourself with v-if, but as mentioned earlier, the modal box is mounted to an element, and the hanging element cannot be removed. How do you do that?

So you can see that there is also a mountDom variable on the top, which allows JS to create the mount element and pass it in, so that Vue can destroy the mount element directly!

In addition to the initial, two functions, OK and Cancel, are reserved for custom events after pressing “OK” and “cancel”, passing in custom functions and assigning values to OK and Cancel.

3. Write JS files, encapsulate methods for invocation, and pass parameters to modal box components

Create a js file in the same directory with the following contents:

import {
	createApp
} from 'vue';

import MyDialog from './MyDialog.vue';

/** * Display custom dialog box *@param {String} Text Indicates the content of the dialog box@param {NodeRequire} Image dialog icon (require image path) *@param {Function} Ok Custom confirm event *@param {Function} Cancel Custom cancel event */
export function showDialog(text, image, ok, cancel) {
	// Create a div element under the body for the modal box vue component to mount
	let mountDom = document.createElement('div');
	mountDom.style.position = 'absolute';
	mountDom.style.left = 0;
	mountDom.style.top = 0;
	document.body.appendChild(mountDom);
	// Mount the component to display. The mount function returns the vUE component instance
	let dialog = createApp(MyDialog).mount(mountDom);
	// Set variables in the vUE instance to pass some data into the VUE
	dialog.text = text;
	dialog.image = image;
	dialog.ok = ok;
	dialog.cancel = cancel;
	// The mounted DOM is passed in so that when the VUE component is closed, the mounted DOM can be destroyed directly for the purpose of destroying the modal box
	dialog.mountDom = mountDom;
}
Copy the code

So this is pretty easy. Define a function that creates a div element and adds it to the body to mount the dialog box component. Then use createApp to mount the dialog box component under the created div element.

Now you know how to pass a value or call a function to a Vue instance in JS.

In the official documentation, the createApp function has the following sentence:

Unlike most application methods, mount does not return the application itself. Instead, it returns the root component instance.

We know that each vue component can be used as an instance, so the mount function not only mounts the component to the specified element, but also returns an example. We can also call variables and functions in this instance to achieve the purpose of passing parameters.

The mount function can be either an instance of a DOM element or a string selector (e.g. ‘#app’, mounted under the element with the id app).

4, test

Now let’s write a button inside the root component and call it:

<template>
  <div class="app">
    <button @click="testShowDialog">Display the modal box</button>
  </div>
</template>

<script>
// Start by introducing the display dialog function in js
import { showDialog } from './components/mydialog.js';

export default {
  name: 'app'.methods: {
    testShowDialog() {
      showDialog(
        'Reminder: what he did, what he did, what he did, what he did, what he did, what he did.'.require('./assets/1.png'),
        () = > {
          console.log('Hit OK');
        },
        () = > {
          console.log('Hit cancel'); }); ,}}};</script>
Copy the code

Effect:

Let’s look at HTML elements:

Combine the js file above to see, I believe I can understand this idea.

5,

It is not difficult to encapsulate a reusable VUE component. First write the style, and then write a matching JS file to pass the parameter to it, for the call.

Sample code repository address