Pain points

When we are in a single page there are multiple pop-up component, generally we will carries on the encapsulation process, while the page will appear multiple components, named for its components, and naming, event name often appears lengthy and let a person have a headache, and when more than one page calls the same component will produce excess duplicate code. For me, I’m more used to using JS for unnecessary HTML, so I came up with the idea of being good at using Vue. Extend +$mount in standalone component development scenarios.

A preliminary attempt to

First we need to figure out what we want to achieve. Since we are invoking the popover with a click, we need to instantiate the component with JS and mount its rendering to the body node at click time.

Encapsulate the popover component we want to use as dialoga.vue (here using elementUI as an example)

<template> <el-dialog title=" test pop-up ":visible="dialogABool" > <div class="content"> <! -- todo --> </div> </el-dialog> </template> <script> import { Component, Vue } from 'vue-property-decorator' @Component({}) export default class DialogA extends Vue { dialogABool = false } </script>Copy the code

Create index.js under its sibling directory for instance mount

import Vue from 'vue'; import dialogA from './DialogA'; const DialogA = Vue.extend(dialogA); var instance = null; export function alertDialogA(){ if(! instance){ instance = new DialogA(); instance.$mount(); document.body.appendChild(instance.$el); } instance.dialogABool = true; }Copy the code

This allows us to control the popover component directly from other components by calling alertDialogA().

The pass participates in the callback

Parameter passing is relatively simple, since it is a method can naturally receive the parameter alertDialogA(params), because extend created by the Vue constructor inherits DialogA component properties, methods, etc., so in index.js parameter assigned to DialogA variables can be.

To receive a callback, the first thing we wanted to do was to use Promise and change index.js:

export function alertDialogA(params){ if(! instance){ instance = new DialogA(); instance.$mount(); document.body.appendChild(instance.$el); } instance.dialogABool = true; instance.params = params; return new Promise((resolve,reject)=>{ instance.promise = { resolve,reject } }) }Copy the code

Resolve () is used to trigger the ‘complete action’ in DialogA, and then is used to invoke the pop-up component, alertDialogA(params).then(()=>{}), Of course, callback parameters can also be passed here to make the component more flexible to use.

Using the thinking

You can see that in index.js we have var instance = null; It is placed outside the alertDialogA method, and a non-null judgment is performed in the method, which means that the popover component is rendered and loaded only when the page is first loaded, so that when we close and open the popover component multiple times, the variables in the component are contaminated. At this point we can build in a hook function init() to initialize the data so that the component can be used without re-rendering.

Var instance = null; var instance = null; var instance = null; Call it inside the method and let go of the judgment. You can do this by adding v-if to dialoga.vue.

The complete code

DialogA.vue

<template> <el-dialog title=" test pop-up ":visible="dialogABool" > <div class="content"> <! </div> <span slot="footer" class="dialog-footer"> <el-button type="primary" @click="onSubmit">  </span> </el-dialog> </template> <script> import { Component, Vue } from 'vue-property-decorator' @Component({}) export default class DialogA extends Vue { dialogABool = false params OnSubmit () {// todo this.promise.resolve(data)}} </script>Copy the code

index.js

import Vue from 'vue'; import dialogA from './DialogA'; const DialogA = Vue.extend(dialogA); var instance = null; export function alertDialogA(params){ if(! instance){ instance = new DialogA(); instance.$mount(); document.body.appendChild(instance.$el); } instance.dialogABool = true; Instance.params = params // get page data instance.init(); return new Promise((resolve,reject)=>{ instance.promise = { resolve,reject } }) }Copy the code

Invoke the popover component page

AlertDialogA ({name: 'test data'}), then ((data) = > {the console. The log (data)})

Conclusion comparing

Those familiar with elementUI will notice that this usage is similar to the lightweight pop-up layers this.$confirm(), this.$alert(), this.$message(), and so on.