Skip to content

Vue2 element-ui el-dialog 命令式开窗Dialog

vue3 写法

文件结构

|-base.vue // 基础组件
|-index.js // 命令式js函数封装
|-input-content.vue // 内容组件
|-use-example.js //使用示例js

封装基础组件

vue

<template>
  <el-dialog v-bind="dialogOption" :visible="true" append-to-body :before-close="beforeClose">
    <!--dialog内容-->
    <component :is="dialogContent" @emit="handleEmit" v-bind="contentOption"/>
  </el-dialog>
</template>
<script setup>

  const props = defineProps({
    // dialog属性 传给el-dialog的属性
    dialogOption: {},
    // 内容组件
    dialogContent: {},
    // 内容组件属性
    contentOption: {
      type: Object
    },
    // 内容事件
    handleEmit: {
      type: Function
    },
    beforeClose: {
      type: Function
    },

  });
</script>

TIP

vue

<component :is="dialogContent" @emit="handleEmit" v-bind="contentOption"/>

约定内容组件抛出事件名称固定为emit

编写命令式js方法

js
import Vue from 'vue';
import Main from './base.vue'

const Constructor = Vue.extend(Main)

/**
 * option 可传入回调方法名称
 * @param option
 * @param {Object} option.dialogOption -- el-dialog属性配置
 * @param {Object} option.dialogContent -- 内容组件
 * @param {Object} [option.contentOption] -- 内容组件属性配置
 */
export function FunctionDialog(option) {

    let {
        dialogOption = {},
        dialogContent,
        contentOption = {},
    } = option;

    dialogOption = {...{width: '58%', title: '开窗', showClose: false}, ...dialogOption}

    function destroy() {
        document.body.removeChild(instance.$el)
        instance.$destroy();
    }

    const instance = new Constructor({
        propsData: {
            dialogOption,
            dialogContent,
            contentOption,
            handleEmit: (emit) => {
                const {name, data, callFunc} = emit;
                option?.[name]?.(data, callFunc, name);
            },
            beforeClose: () => {
                destroy()
            },
        },
    });
    instance.$mount();
    document.body.appendChild(instance.$el);
    return destroy;
}

使用示例

编写内容组件

vue

<template>
  <div>
    <el-input :placeholder="placeholder" v-model="str"></el-input>
    <el-button @click="handleClickConfirm">确定</el-button>
    <el-button @click="handleClickCancel">取消</el-button>
  </div>
</template>
<script>
  export default {
    props: {
      placeholder: {}
    },
    data() {
      return {
        str: ''
      }
    },
    methods: {
      handleClickConfirm() {
        this.emitFunc({
          name: 'confirm',
          data: this.str,
          callFunc: () => {
            console.log('回调函数')
          }
        })
      },
      handleClickCancel() {
        this.emitFunc({
          name: 'cancel'
        })
      },
      /**
       * 所有内容组件都必须按照此数据结构抛出事件
       * @param options
       * @param {String} options.name 事件名称
       * @param {Object} [options.data] 事件数据
       * @param {Function} [options.callFunc] 事件回调函数
       */
      emitFunc(options) {
        const {name, data, callFunc} = options
        this.$emit('emit', options)
      }
    }
  }
</script>

使用

js
import {FunctionDialog} from './index.js'
import InputContent from './input-content.vue'


const destroy = FunctionDialog({
    dialogContent: InputContent,
    dialogOption: {
        title: '输入文字input',
        width: '400px'
    },
    contentOption: {
        placeholder: '内容组件的placeholder'
    },
    // 此处自己写内容组件中emitFunc的name方法名称
    confirm: (data, callFunc, name) => {
        // 打印InputContent的input字符串
        console.log('data', data)
        // 调用回调函数
        callFunc()
        // 卸载命令式dialog
        destroy()
    },
    cancel: (data, callFunc, name) => {
        destroy()
    }


})

TIP

这种方式使用命令式弹窗,使用起来方便快捷,复用起来非常简便

包括el-drawer等其它vue2组件库的组件都可以类似封装为命令式函数使用

/src/technology/dateblog/2025/04/20250418-vue2-element-ui-el-dialog-%E5%91%BD%E4%BB%A4%E5%BC%8F%E5%BC%80%E7%AA%97dialog.html