这是一个封装了表单组件的思想。它使用了Vue.js框架和Element UI库来创建可复用的表单组件。该组件接受props作为输入,包括表单的各种配置项和数据。根据配置项的不同,组件内部会生成对应的表单元素,如输入框、下拉框、单选框、复选框等。同时,组件还提供了上传附件和预览功能。
该封装思想的优点在于可以减少代码的冗余,提高代码的复用性和维护性。通过将表单的配置项和数据作为props进行输入,可以在使用组件的地方轻松定制表单的样式和行为,同时也可以方便地对表单的数据进行处理和提交。
总体来说,该封装思想利用了Vue.js的组件化和响应式原理,使得表单的开发和使用更加简洁高效。 新增 编辑 详细 通用 废话不多说直接上代码
form组件
<!-- Dom模板 -->
<template>
<div>
<!-- Dom内容 -->
<el-form
:model="ruleForm"
ref="ruleForm"
:label-width="labelWidth"
class="el-row demo-ruleForm"
:label-position="labelPosition"
>
<el-form-item
v-for="(item, index) in formList"
:key="index"
:label="item.label"
:prop="item.field"
:rules="detail ? false : item.rules"
:class="item.colWidth"
>
<!-- 输入框 -->
<template v-if="item.type === 'input'">
<el-input
:placeholder="item.placeholder"
clearable
:disabled="disabled"
v-model="ruleForm[`${item.field}`]"
/>
</template>
<!-- 下拉框 -->
<template v-if="item.type === 'select'">
<el-select
v-model="ruleForm[`${item.field}`]"
:placeholder="item.placeholder"
:disabled="disabled"
:multiple="item.multiple"
style="width: 100%"
@change="changeSelect"
>
<el-option
v-for="(element, i) in item.options"
:label="element.label"
:value="`${element.value}`"
:key="i"
/>
</el-select>
</template>
<!-- 单选框 -->
<template v-if="item.type === 'radio'">
<el-radio-group
v-model="ruleForm[`${item.field}`]"
:disabled="disabled"
>
<el-radio
v-for="(element, i) in item.options"
:key="i"
:label="`${element.value}`"
>
{{ element.label }}
</el-radio>
</el-radio-group>
</template>
<!-- 复选框 -->
<template v-if="item.type === 'checkbox'">
<el-checkbox-group
v-model="ruleForm[`${item.field}`]"
:disabled="disabled"
>
<el-checkbox
v-for="(city, i) in item.cities"
:label="city"
:name="city"
:key="i"
>
{{ city }}
</el-checkbox>
</el-checkbox-group>
</template>
<!--文本框 -->
<template v-if="item.type === 'textarea'">
<el-input
:maxlength="item.maxLenght"
type="textarea"
:rows="item.rowsHeight"
:disabled="disabled"
:placeholder="item.placeholder"
v-model="ruleForm[`${item.field}`]"
/>
</template>
<!-- 时间选择 -->
<template v-if="item.type === 'date'">
<el-date-picker
v-model="ruleForm[`${item.field}`]"
align="right"
style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss"
:disabled="disabled"
type="date"
placeholder="选择日期"
:picker-options="item.pickerOptions"
>
</el-date-picker>
</template>
<!-- 附件 -->
<template v-if="item.type === 'upload'">
<el-upload
:action="item.action"
list-type="picture-card"
:headers="item.headers"
:disabled="disabled"
class="upload-demo"
:multiple="item.multiple"
:data="ruleForm[`${item.field}`]"
:file-list="ruleForm[`${item.field}`]"
:on-change="uploadFile"
:auto-upload="false"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
>
<i slot="default" class="el-icon-plus"></i>
</el-upload>
</template>
</el-form-item>
</el-form>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
export default {
props: {
detail: {
type: Boolean,
default: () => false,
},
disabled: {
type: Boolean,
default: () => false,
},
//回显数据
fromItem: {
type: Object,
default: () => null,
},
labelWidth: {
type: String,
default: () => "100px",
},
// 表单数据
formNewList: {
type: Array,
default: () => [],
},
labelPosition: {
type: String,
default: () => "right",
},
},
watch: {
formNewList: {
immediate: true, // 立即触发监听函数
handler() {
this.formList = this.formNewList;
this.defaultFun();
},
},
},
data() {
return {
ruleForm: {},
formList: [],
dialogImageUrl: "",
dialogVisible: false,
};
},
methods: {
//下拉框下拉事件
changeSelect(row) {
// console.log(row);
this.$emit("changeSelect", row);
},
//上传附件
uploadFile(file, fileList) {
this.formList.forEach((item) => {
if (item.type === "upload") {
this.$set(this.ruleForm, item.field, fileList);
}
});
},
//删除附件
handleRemove(file) {
this.formList.forEach((item) => {
let fileList = this.ruleForm[`${item.field}`];
if (item.type === "upload") {
fileList.forEach((element, i) => {
if (file.uid === element.uid) {
fileList.splice(i, 1);
}
});
}
this.$set(this.ruleForm, item.field, fileList);
});
},
//附件预览
handlePictureCardPreview(file) {
console.log(file);
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
//表单默认状态
defaultFun() {
if (this.fromItem !== null) {
// 数据回显
this.ruleForm = { ...this.ruleForm, ...this.fromItem };
} else {
//设置默认值
this.formList.forEach((item) => {
if (item.cities) {
this.$set(this.ruleForm, item.field, []);
} else {
this.$set(this.ruleForm, item.field, "");
}
if (item.type === "radio") {
this.$set(this.ruleForm, item.field, "1");
}
if (item.type === "upload") {
this.$set(this.ruleForm, item.field, []);
}
});
}
console.log(this.ruleForm);
},
//from表单点击事件
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$emit("headdenForm", this.ruleForm);
}
});
},
//清空表单
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
//引用
<!--index-->
<template>
<div ref="ScaleBox" class="ScaleBox">
<!-- Form 组件-->
<Form
@headdenForm="headdenForm"
:fromItem="fromItem"
@changeSelect="changeSelect"
:formNewList="formList"
:detail="edit"
:disabled="edit"
ref="VabForm"
/>
<div class="cardfooter">
<el-button @click="cancellation">取消</el-button>
<el-button @click="save" type="primary">保存</el-button>
</div>
</div>
</template>
<script>
// import a from './a'; // 引入组件
import { rules } from "./view/vabForm.js";
// import {addFun} from 'cli-data'
export default {
name: "",
components: {
// eslint-disable-next-line vue/no-unused-components
rules,
},
data() {
return {
msg: "测试",
title: "相关附件",
edit: false,
action: true,
header: false,
width: 1920,
height: 1080,
dataList: [
{ name: "张三", age: 19, id: 1 },
{ name: "李四", age: 20, id: 2 },
],
formList: [],
// 模拟数据 详细 测试
fromItem: {
id: "Shanghai",
id1: "选项4",
name: "用户名",
radioId: "2",
checkboxId: ["上海", "北京"],
textareaIner: "textarea",
dateTime: "2023-09-12 00:00:00",
uploadList: [
{
name: "小梨猫.jpg",
size: 160517,
uid: 1695291434025,
url: "https://ts1.cn.mm.bing.net/th?id=OIP-C.Zte3ljd4g6kqrWWyg-8fhAHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.5&pid=3.1&rm=2",
},
],
},
optionss: [
{
value: "选项1",
label: "黄金糕",
},
{
value: "选项2",
label: "双皮奶",
},
{
value: "选项3",
label: "蚵仔煎",
},
{
value: "选项4",
label: "龙须面",
},
{
value: "选项5",
label: "北京烤鸭",
},
],
cities: [
{
value: "Beijing",
label: "北京",
},
{
value: "Shanghai",
label: "上海",
},
{
value: "Nanjing",
label: "南京",
},
{
value: "Chengdu",
label: "成都",
},
{
value: "Shenzhen",
label: "深圳",
},
{
value: "Guangzhou",
label: "广州",
},
],
};
},
// 生命周期 - 创建完成(访问当前this实例)
created() {},
// 生命周期 - 挂载完成(访问DOM元素)
mounted() {
this.getList();
},
methods: {
getList() {
const dataList = rules();
dataList.forEach((item) => {
if (item.field === "id") {
item.options = this.cities;
}
if (item.field === "id1") {
item.options = this.optionss;
}
});
this.formList = dataList;
},
//下拉框下拉事件
changeSelect(element) {
console.log(element);
},
//按钮列点击方法
headelActionShow(element) {
console.log(element);
},
//获取form 对象
headdenForm(element) {
console.log(element);
},
//保存
save() {
this.$refs.VabForm.submitForm("ruleForm");
},
//取消
cancellation() {
this.$refs.VabForm.resetForm("ruleForm");
},
},
};
</script>
<style scoped>
/* @import url(''); 引入css类 */
.ScaleBox {
/* position: absolute; */
/* top: 50%; */
/* left: 50%; */
z-index: 999;
/* width: 1820px; */
width: 100%;
/* height: 1080px; */
background-size: 100% 100%;
-ms-transition: 0.3s;
transition: 0.3s;
/* transform: scale(var(--scale)) translate(-50%, -50%); */
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.cardfooter {
width: 100%;
/* padding: 20px; */
position: fixed;
bottom: 20px;
right: 30px;
text-align: right;
/* background: ; */
}
</style>
vabForm.js
export const rules = () => {
return [
{
field: 'id',
type: 'select',
label: '部门',
multiple:false,
placeholder: '请选择部门',
colWidth: 'el-col-10',
options: [
{
label: '部门一',
value: 90000,
},
{
label: '部门二',
value: 50000,
}
],
rules: [
{
required: true,
message: '请选择部门',
trigger: 'change'
},
]
},
{
field: 'id1',
type: 'select',
label: '部门1',
multiple:false,
placeholder: '请选择部门1',
colWidth: 'el-col-10',
options: [
{
label: '部门一1',
value: 2345678,
},
{
label: '部门二2',
value: 6543450,
}
],
rules: [
{
required: true,
message: '请选择部门',
trigger: 'change'
},
]
},
{
field: 'name',
label: '用户名',
placeholder: '请输入活动名称',
type: 'input',
maxLenght: 20,
colWidth: 'el-col-24',
rules: [
{ required: true, message: '请输入活动名称', trigger: ['blur', 'change'] },
]
},
{
field: 'radioId',
type: 'radio',
label: '备选项',
colWidth: 'el-col-24',
options: [
{
label: '选项一',
value: '1',
},
{
label: '选项二',
value: '2',
}
],
rules: [
{
required: true,
message: '请选择备选项',
trigger: 'blur'
},
]
},
{
field: 'checkboxId',
type: 'checkbox',
label: '状态',
colWidth: 'el-col-24',
cities: ['上海', '北京', '广州', '深圳'],
rules: [
{
required: true,
message: '请选择状态',
trigger: 'change'
},
]
},
{
field: 'textareaIner',
label: '内容',
placeholder: '请输入内容',
maxLenght: 300,
type: 'textarea',
rowsHeight: 4,
colWidth: 'el-col-24',
rules: [
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] }
]
},
{
field: 'dateTime',
label: '内容',
placeholder: '请输入内容',
type: 'date',
pickerOptions: pickerOptions(),
colWidth: 'el-col-24',
rules: [
{ required: true, message: '请输入内容', trigger: 'blur' }
]
},
{
field: 'uploadList',
label: '附件',
headers: {},
action: '/action',
type: 'upload',
multiple: true,
colWidth: 'el-col-24',
rules: [
{ required: true, message: '请上传附件', trigger: ['blur', 'change'] },
callback()
]
},
]
}
function callback() {
return {
validator: function (rule, value, callback) {
console.log(rule, value);
if (value) {
callback()
}
}
}
}
function pickerOptions() {
return {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: '今天',
onClick(picker) {
picker.$emit('pick', new Date());
}
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
}
}, {
text: '一周前',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}]
}
}