el-dialog-form组件封装,真的好用,可以让你开发效率提高
请看效果图,支持elementUI所有表单组件

1、新建DialogForm.vue文件
<template>
<div class="base-dialog">
<el-dialog
:type="type"
:custom-class="customClass"
:close-on-click-modal="closeOnClickModal"
:visible="visible"
:title="title"
:width="width"
:show-close="true"
:before-close="beforeClose"
>
<!-- <el-card> -->
<el-form
ref="d-form"
:model="form"
:label-position="labelPosition"
label-width="120px"
>
<el-row :gutter="20">
<el-col
v-for="(item, index) in items"
v-show="item.hidden ? !item.hidden(form) : true"
:key="index"
:span="item.span || 20"
>
<el-form-item
:label="item.label"
:prop="item.prop"
:rules="item.hidden && item.hidden(form) ? null : item.rules"
>
<el-tooltip
:disabled="!item.tip"
effect="dark"
:content="item.tip"
placement="top"
>
<slot
v-if="item.elName === 'slot'"
:name="item.prop"
:form="form"
></slot>
<el-component
v-else
v-model="form[item.prop]"
:el-name="item.elName"
:on="item.on || {}"
:attrs="item.attrs || {}"
:options="item.options || []"
:disabled="item.disabled ? item.disabled(form) : false"
></el-component>
</el-tooltip>
</el-form-item>
</el-col>
<slot></slot>
</el-row>
</el-form>
<!-- </el-card> -->
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="onCancel">取 消</el-button>
<el-button type="primary" size="small" @click="onSubmit"
>确 定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
// 验证器文档地址:https://github.com/yiminghe/async-validator
import elComponent from "@/lib/elComponent.js";
export default {
name: "ElDialogForm",
components: {
elComponent
},
props: {
closeOnClickModal: { type: Boolean, default: false }, // 是否可以点击关闭
type: String, // 对话框类型:1.基础表单[base-dialog-form] 2.表格[base-dialog-table] 3.全屏 [base-dialog-fullscreen]
// 是否显示dialog
visible: {
type: Boolean,
default: false
},
// 标题
title: {
type: String,
default: ""
},
// 宽度
width: {
type: String,
default: ""
},
// 表单项
items: {
type: Array,
default: () => []
},
// 表单值
form: {
type: Object,
default: () => {
return {};
}
},
labelPosition: {
type: String,
default: "right"
}
},
computed: {
customClass() {
let className = "";
switch (this.type) {
case "form":
className = "base-dialog-form";
break;
case "table":
className = "base-dialog-table";
break;
case "fullscreen":
className = "base-dialog-fullscreen";
break;
}
return className;
}
},
created() {
this.type === "fullscreen" && (this.fullscreen = true);
},
methods: {
onSubmit() {
this.$refs["d-form"].validate(valid => {
if (valid) {
this.$emit("submit", this.form);
}
});
},
onCancel() {
this.$emit("update:visible", false);
this.$emit("cancel");
this.$refs['d-form'].resetFields();
},
close() {
this.$emit("update:visible", false);
this.$refs['d-form'].resetFields();
},
beforeClose() {
this.$emit("update:visible", false);
this.$refs['d-form'].resetFields();
}
}
};
</script>
<style lang="scss">
.el-form-item {
margin-bottom: 15px !important;
}
.base-dialog {
text-align: left;
.el-dialog__wrapper {
// overflow: hidden;
.el-dialog {
display: flex;
flex-direction: column;
.el-dialog__header {
height: 40px;
line-height: 40px;
padding: 0px 20px;
background: #eff3fa;
color: #fff;
border-bottom: 1px solid #dcdfe6;
border-top-left-radius: 0;
border-top-right-radius: 0;
.el-dialog__title {
font-size: 16px;
// font-weight: bold;
}
.el-dialog__headerbtn {
top: 12px;
}
}
.el-dialog__body {
flex: 1;
overflow: auto;
padding: 20px !important;
}
.el-dialog__footer {
text-align: center;
border-top: 1px solid #eee;
padding: 8px 20px;
background: #fefefe;
}
}
.base-dialog-form {
height: auto;
margin-top: 15vh !important;
.el-dialog__body {
padding: 20px 20px 0 20px !important;
}
.el-dialog__footer {
border: none;
padding: 10px 20px 20px;
background: none;
}
.custom-table {
// 取消表格下边线
tbody tr:last-child td {
border-bottom: none !important;
}
}
}
.base-dialog-table {
height: 90vh;
margin-top: 5vh !important;
.el-dialog__body {
}
}
.base-dialog-fullscreen {
height: 100vh;
width: 100vw;
.el-dialog__body {
padding: 10px;
}
}
}
}
.el-date-editor.el-input{
width: 100% !important;
}
.el-select {
width: 100% !important;
}
.el-range-editor.el-input__inner{
width: 100% !important;
}
.el-cascader{
width: 100% !important;
}
</style>
2、新建lib文件夹,文件夹下面创建三个文件,分别是defaultAttrs.js,elComponent.js,slots.js,代码分别如下
defaultAttrs.js
const map = { 'el-time-picker': { 'size': 'small', 'placeholder': '请选择时间', 'value-format': 'HH:mm:ss', }, 'el-date-picker': { 'size': 'small', 'placeholder': '请选择日期', 'value-format': 'yyyy-MM-dd', 'type': 'date', 'start-placeholder': '开始日期', 'end-placeholder': '结束日期', }, }; export function getDefaultAttrs(elName) { return ( map[elName] || { size: 'small', } ); }
elComponent.js
// 获取默认attrs import { getDefaultAttrs } from './defaultAttrs.js'; // 获取子组件 import { getChild } from './slots.js'; // 导出新组件 export default { props: ['value', 'elName', 'options', 'disabled'], name: 'el-component', render(h) { const self = this; const slots = Object.keys(this.$slots) .reduce((arr, key) => arr.concat(this.$slots[key]), []) .map(vnode => { vnode.context = this._self; return vnode; }); // 获取子组件,如果有的话 const child = getChild(this.elName, h, this.options); // 获取事件监听 const events = this.$attrs.on || {}; // 渲染函数中没有与 v-model 的直接对应——必须自己实现相应的逻辑 events['input'] = function(event) { self.$emit('input', event); }; // 参数传进来的attrs const attrsinset = this.$attrs.attrs || {}; // 默认的attrs const defaultAttrs = getDefaultAttrs(this.elName); // 根据type渲染组件 return h( `${this.elName}`, { on: events, props: { ...this.$props, ...attrsinset, }, // 透传 scopedSlots scopedSlots: this.$scopedSlots, attrs: { ...attrsinset, ...defaultAttrs, disabled: this.disabled, }, }, [...slots, ...child], ); }, };
slots.js
const map = { 'el-radio-group': 'el-radio', 'el-checkbox-group': 'el-checkbox', 'el-select': 'el-option', }; export function getChild(elName, h, options = []) { const arr = []; if (map[elName] !== undefined) { for (const i of options) { const label = elName === 'el-select' ? i.label : i.value; const value = elName === 'el-select' ? i.value : i.label; arr.push( h( `${map[elName]}`, { props: { label, value, }, }, [h('span', i.label)] ) ); } } return arr; }
3、如何在页面调用,代码如下
//在main.js中全局注册组件 import DialogFrom from '@/components/Table/DialogForm.vue' Vue.component('DialogFrom', DialogFrom)
<!-- 按钮触发弹窗 -->
<el-button type="primary" size="small" @click="dialog = true">打开表单</el-button>
<!-- 表单 -->
<DialogFrom
ref="DialogFrom"
type="form"
:visible.sync="dialog"
title="表单标题"
width="50%"
:items="items"
:form="form"
@submit="onSubmit"
>
<template slot="image">
<div
class="upLoadPicBox"
title="750*750px"
@click="modalPicTap('1', 'image')"
>
<div v-if="form.image" class="pictrue">
<img :src="form.image" />
</div>
<div v-else class="upLoad">
<i class="el-icon-picture cameraIconfont" />
</div>
</div>
</template>
</DialogFrom>
//JS的data部分 form: { input: "", inputNumber: 0, switch: false, timePicker: "", datePicker: "", radioGroup: 1, checkboxGroup: [], select: [], checkbox: 1, datePickerTwo: "", image: "", cascader: [] }, dialog: false, items: [ { elName: "el-input", span: 12, label: "普通输入", prop: "input", rules: [ { required: true, message: "请输入名称", trigger: "blur" } ], attrs: { placeholder: "请输入名称" }, hidden: function() { return false; }, disabled: e => { if (this.form.checkbox == 1) { return true; } else { return false; } }, on: { blur: e => { console.log(e); } } }, { elName: "el-date-picker", span: 12, label: "日期选择", prop: "datePicker", attrs: { "value-format": "yyyy-MM-dd" } }, { elName: "el-date-picker", span: 12, label: "日期范围选择", prop: "datePickerTwo", attrs: { type: "daterange" } }, { elName: "el-time-picker", span: 12, label: "时间选择", prop: "timePicker", on: {} }, { elName: "el-switch", span: 12, label: "开关", prop: "switch", on: {} }, { elName: "slot", span: 12, label: "上传图片", prop: "image" }, { elName: "el-radio-group", span: 12, label: "单选框组", prop: "radioGroup", tip: "", options: [ { label: "苹果", value: 1 }, { label: "西瓜", value: 2 } ], on: { change: e => {} } }, { elName: "el-cascader", span: 12, label: "下拉级联选择", prop: "cascader", options: [], attrs: { placeholder: "请选择级联", multiple: false }, on: { change: e => { console.log("-----------"); console.log(e); } } }, { elName: "el-select", span: 12, label: "下拉选择", prop: "select", options: [ { label: "鼠标", value: 1 }, { label: "键盘", value: 2 } ], attrs: { placeholder: "请输入名称", multiple: true }, on: { change: e => { console.log("-----------"); console.log(e); } } }, { elName: "el-checkbox", span: 12, label: "选择", prop: "checkbox", attrs: { label: "我同意", "true-label": 1, "false-label": 0 }, on: { change: e => { console.log("-----------"); console.log(e); } } }, { elName: "el-checkbox-group", span: 12, label: "多选框组", prop: "checkboxGroup", options: [ { label: "鼠标", value: 1 }, { label: "键盘", value: 2 }, { label: "电脑", value: 3 } ], on: { change: e => { console.log("-----------"); console.log(e); } } } ],
//JS的methods方法部分 modalPicTap(tit, type) { const _this = this; const attr = []; this.$modalUpload(function(img) { if (tit === "1" && type == "image") { _this.form.image = img[0]; } }, tit); }, onSubmit(form) { console.log(form); },
参数说明
| 参数名 | 说明 | 类型 | 可选值 | 默认值 |
| visible | 是否显示dialog | Boolean | true | false |
| title | 标题 | String | - |
- |
| width | 表单宽度 | String | - | - |
| items | 表单项,详细见下方说明 | Array | - | [] |
| form | 初始表单值 | Object | - | {} |
使用说明
#### 介绍
基于element-ui封装的弹窗式表单组件
#### 使用说明
#### 参数说明
| 参数名 | 说明 | 类型 | 可选值 | 默认值 |
|---------|-------------|---------|------|-------|
| visible | 是否显示dialog | Boolean | true | false |
| title | 标题 | String | - | - |
| width | 表单宽度 | String | - | - |
| items | 表单项,详细见下方说明 | Array | - | [] |
| form | 初始表单值 | Object | - | {} |
#### items参数说明
| 参数名 | 说明 | 类型 | 可选值 | 默认值 |
|----------|--------------|---------|------|-------|
| elName | 表单项的类型,element ui的组件标签或者slot,必填 | String | el-input/el-input-number/el-radio-group/el-checkbox-group/el-select/el-switch/el-time-picker/el-date-picker/slot | - |
| span | el-col的span值 | Number | - | 20 |
| label | 表单项label | String | - | - |
| prop | 表单项key | String | - | - |
| tip | 文字提示 | String | - | - |
| rules | 表单验证规则,验证器文档地址:https://github.com/yiminghe/async-validator | Array | - | - |
| hidden | 隐藏条件函数,返回true/false来控制显示隐藏 | Function | - | - |
| disabled | 禁用条件函数,返回true/false来控制禁用启用 | Function | - | - |
| options | 选择项数组,仅type等于radio-group/checkbox-group/select生效,详细见下方说明 | Array | - | - |
| on | 事件监听,key->value形式,key值同element-ui的Events,value为一个函数,详见element-ui文档 | Object | - | - |
| attrs | 属性参数,key->value形式,key值同element-ui的Attributes,详见element-ui文档 | Object | - | - |
#### options参数说明
| 参数名 | 说明 | 类型 | 可选值 | 默认值 |
|-------|----------|--------|-----|-----|
| label | 显示的label | String | - | - |
| value | 选中的value | Any | - | - |
#### elName==='slot'
绑定值为:form
浙公网安备 33010602011771号