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); },
标签:el,form,label,elName,dialog,type From: https://www.cnblogs.com/zcm1688/p/17469907.html