Vue2 element-ui el-dialog 命令式开窗Dialog
文件结构
|-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组件库的组件都可以类似封装为命令式函数使用