When implementing requirements using Vue + Element, it is common to encounter multiple popover requirements in a single Vue file

<! --*.vue-->
<template>
  <el-dialog :visible="visible1">Play box 1</el-dialog>
  <el-dialog :visible="visible2">Play box 2</el-dialog>
</template>

<script>
export default {
  return {
    visible1: false.visible2: false}}</script>
Copy the code

This writing method is prone to the problem of template overcrowding when the file content is large, and external management of the popover component switch status visible is required

How it can be improved

Service usage borrowed from NgZoro’s Modal component

Consider wrapping an El-Dialog as a Service for use

<! --*.vue-->
<script>
// I used to set SRC to alias @
import DialogService from '@/service/dialog'
showDialog() {
  DialogService({ /* Data */ needed in the box})}</script>
Copy the code

How to implement

  • First, you need to define the entrance of DialogService to pass through internallyVue.extendI inherits the component template
// src/service/dialog/index.js
import Vue from 'vue'

import dialogTemplate from './dialogTemplate.vue'
const DialogConstructor = Vue.extend(dialogTemplate)

import { isPlainObject } from 'lodash'

export default options => {
  let instance
  return function() {
    // In singleton mode, lazy return to popover instance
    if (instance) {
      instance.visible = true
      return instance
    }

    instance = new DialogConstructor({
      data: isPlainObject(options) ? { ...options } : {}
    })

    instance.$mount()
    document.body.appendChild(instance.$el)
    instance.visible = true

    // Expose the instance for subsequent Ref operations
    return instance
  }
}
Copy the code
  • Next is the dialogTemplate implementation, can be adjusted according to the actual business, the following code is for reference only
<! --src/service/dialog/dialogTemplate.vue--><template>
  <el-dialog :title="title" :visible.sync="visible">
    <el-table :height="300" :data="tblData">
      <el-table-column
        props="prop1"
        label="col1"
        align="center"
      ></el-table-column>
      <el-table-column
        props="prop2"
        label="col2"
        align="center"
      ></el-table-column>
      <el-table-column
        Props="prop3"
        label="col3"
        align="center"
      ></el-table-column>
    </el-table>

    <div slot="footer" class="dialog-footer">
      <el-button v-show="submitVisible" size="small" @click="handleCancel">
        {{ cancelText }}
      </el-button>
      <el-button
        v-show="cancelVisible"
        size="small"
        type="primary"
        @click="handleSubmit"
      >
        {{ submitText }}
      </el-button>
    </div>
  </el-dialog>
</template>

<script>
import { isFunction } from 'lodash'

export default {
  data() {
    return {
      visible: false.title: ' '.labelWidth: '100px'.content: null.tblData: []./* footer */
      submitVisible: true.submitText: 'sure'.onSubmit: null.cancelVisible: true.cancelText: 'cancel'.onCancel: null}},methods: {
    handleSubmit() {
      if (isFunction(this.onSubmit)) {
        this.onSubmit({ done: this._done })
      }
    },
    handleCancel() {
      if (isFunction(this.onCancel)) {
        this.onCancel({
          done: this._done
        })
      }
    },
    _done() {
      this.visible = false
    },
    _destory() {
      this.$destroy()
    }
  }
}
</script>

Copy the code

Used in business code

  • Render a popover with a table
<! --*.vue-->
<template>
  <el-button @click="showDialog">Call form</el-button>
</template>
<script>
import DialogService from '@/service/dialog'
export default {
  data() {
    return {
      dialogInstance: null}}methods: {
    showDialog() {
      this.dialogInstance = dialogService({
        title: 'Dialog with table'.onCancel: ({ done }) = > done()
      })
    }
  }
}
</script>
Copy the code