# 新建 Form.vue
src/components/Form.vue
<template>
<div>
<el-form
ref="form"
:model="form"
:inline="inline"
:rules="rules"
:label-width="labelWidth"
class="form"
>
<el-form-item
:label="item.title"
:prop="item.key"
v-for="item in options"
:key="item.key"
>
<el-input
:size="size"
v-model="form[item.key]"
v-if="item.type === 'input'"
:placeholder="'请输入' + item.title"
clearable
></el-input>
<el-input
:size="size"
type="textarea"
:autosize="{ minRows: 3, maxRows: 6 }"
:placeholder="'请输入' + item.title"
v-model="form[item.key]"
v-if="item.type === 'text'"
>
</el-input>
<el-switch
:size="size"
v-model="form[item.key]"
v-if="item.type === 'switch'"
active-color="#13ce66"
inactive-color="#ff4949"
>
</el-switch>
<el-time-picker
:size="size"
:placeholder="'请选择' + item.title"
v-model="form[item.key]"
value-format="HH:mm:ss"
v-if="item.type === 'time'"
>
</el-time-picker>
<el-date-picker
type="date"
:placeholder="'请选择' + item.title"
value-format="yyyy-MM-dd"
:size="size"
v-model="form[item.key]"
v-if="item.type === 'date'"
></el-date-picker>
<el-date-picker
type="datetime"
:placeholder="'请选择' + item.title"
value-format="yyyy-MM-dd HH:mm:ss"
:size="size"
v-model="form[item.key]"
v-if="item.type === 'datetime'"
></el-date-picker>
<el-date-picker
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd HH:mm:ss"
:size="size"
v-model="form[item.key]"
v-if="item.type === 'date-to-date'"
></el-date-picker>
<el-date-picker
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd HH:mm:ss"
:size="size"
v-model="form[item.key]"
v-if="item.type === 'datetime-to-datetime'"
></el-date-picker>
<el-input-number
:size="size"
v-model="form[item.key]"
v-if="item.type === 'number'"
></el-input-number>
<el-select
:size="size"
v-model="form[item.key]"
v-if="item.type === 'select'"
clearable
:placeholder="'请选择' + item.title"
>
<el-option
v-for="data in item.option.data"
:key="data[item.option.key]"
:label="data[item.option.label]"
:value="data[item.option.value]"
>
</el-option>
</el-select>
<el-radio-group
:size="size"
v-model="form[item.key]"
v-if="item.type === 'radio'"
>
<el-radio
v-for="data in item.option.data"
:key="data[item.option.key]"
:label="data[item.option.value]"
>{
{ data[item.option.label] }}</el-radio
>
</el-radio-group>
<el-checkbox-group
:size="size"
v-model="form[item.key]"
v-if="item.type === 'checkbox'"
>
<el-checkbox
v-for="data in item.option.data"
:key="data[item.option.key]"
:label="data[item.option.value]"
>{
{ data[item.option.label] }}</el-checkbox
>
</el-checkbox-group>
</el-form-item>
<slot name="file"></slot>
<el-form-item v-if="search">
<el-button type="primary" :size="size" @click="onSearch">
{
{ searchText }}
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "index",
props: {
// 表单
form: {
type: Object,
default: function() {
return {};
}
},
// 表单配置
options: {
type: Array,
default: function() {
return [];
}
},
// 表单验证规则
rules: {
type: Object,
default: function() {
return {};
}
},
// 是否行内表单
inline: {
type: Boolean,
default: function() {
return false;
}
},
// 是否开启搜索
search: {
type: Boolean,
default: function() {
return false;
}
},
// 搜索按钮的文字
searchText: {
type: String,
default: function() {
return "查询";
}
},
// 表单表头宽度
labelWidth: {
type: String,
default: function() {
return "80px";
}
},
// 控件大小
size: {
type: String,
default: function() {
return "medium";
}
}
},
data() {
return {};
},
mounted() {
// 动态添加验证
this.addRules(this.options);
// 初始化完成清除一下表单验证规则
this.$nextTick(function() {
this.$refs.form.clearValidate();
});
},
methods: {
/**
* @description: 点击了搜索
* @author: chenbz
* @date: 2021/4/25
*/
onSearch() {
this.$refs.form.validate(valid => {
if (valid) {
this.$emit("onSearch", this.form);
} else {
// console.log("error submit!!");
return false;
}
});
},
/**
* @description: 动态添加表单验证
* @author: chenbz
* @date: 2021/4/27
*/
addRules(options) {
for (let i = 0; i < options.length; i++) {
// 判断是否需要添加验证
if (options[i].rules) {
// 判断用户是否已经自定义验证了
if (!this.rules[options[i].key]) {
// 动态生成验证方法
let data = [
{
required: true,
message: "",
trigger: ""
}
];
// 动态添加验证方式:失去焦点触发/确认时触发
if (options[i].type === ("input" || "text")) {
data[0].message = "请输入" + options[i].title;
data[0].trigger = "blur";
} else {
data[0].message = "请选择" + options[i].title;
data[0].trigger = "change";
}
// 触发vue更新
this.$set(this.rules, options[i].key, data);
}
}
}
}
}
};
</script>
<style scoped></style>
# 引入页面
src/views/home.vue
<template>
<div>
<div>
<MyForm
:form="formData.form"
:inline="true"
:search="true"
:searchText="'立刻查询'"
:options="formData.options"
:rules="formData.rules"
:labelWidth="formData.labelWidth"
@onSearch="onSearch"
></MyForm>
<el-divider></el-divider>
<MyForm
:form="formData.form"
:options="formData.options"
:rules="formData.rules"
:labelWidth="formData.labelWidth"
@onSearch="onSearch"
></MyForm>
<el-divider></el-divider>
</div>
</div>
</template>
<script>
import MyForm from "@/components/Form.vue";
export default {
name: "home",
components: {
MyForm
},
data() {
return {
formData: {
form: {
date: "",
sex: "",
name: ""
},
options: [
{
title: "日期",
key: "date",
type: "date",
rules: true
},
{
title: "性别",
key: "sex",
type: "select",
option: {
data: [
{
id: 1,
title: "女",
type: 0
},
{
id: 2,
title: "男",
type: 1
}
],
key: "id", // 指定key对应data的字段
label: "title", // 指定label对应data的字段
value: "type" // 指定value对应data的字段
}
},
{
title: "名字",
key: "name",
type: "input",
rules: true
}
],
rules: {},
labelWidth: "80px"
}
};
},
mounted() {},
methods: {
// 搜索
onSearch(data) {
console.log(data);
}
}
};
</script>
<style scoped></style>
# 自定义图片上传
<template>
<div>
<div>
<MyForm
:form="formData.form"
:options="formData.options"
:rules="formData.rules"
:labelWidth="formData.labelWidth"
@onSearch="onSearch"
>
<template slot="file">
<el-form-item label="文件上传">
<el-upload
action=""
:show-file-list="false"
:on-change="handleChange"
:auto-upload="false"
>
<img v-if="formData.form.img" :src="formData.form.img" alt="" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
</template>
</MyForm>
<el-divider></el-divider>
</div>
</div>
</template>
<script>
import MyForm from "@/components/Form.vue";
export default {
name: "home",
components: {
MyForm
},
data() {
return {
formData: {
form: {
date: ""
},
options: [
],
rules: {},
labelWidth: "80px"
}
};
},
mounted() {},
methods: {
handleChange(file, fileList) {
fileList;
this.formData.form.img = URL.createObjectURL(file.raw);
}
}
};
</script>
<style></style>
使用
template
包含自定义的内容,slot
一定要是file
上传组件根据业务而定,我预留了一个
slot
插槽用来显示自定义的上传组件
# 参数说明
属性 | 描述 | 默认值 | 必需 |
---|---|---|---|
form | form表单 | {} | 是 |
options | 表单配置 | [] | 是 |
inline | 是否开启行内表单 | false | 否 |
search | 是否开启搜索 | false | 否 |
searchText | 搜索按钮文字 | 查询 | 否 |
rules | 表单验证规则 | {} | 否 |
labelWidth | 表单表头宽度 | 80px | 否 |
size | 控件大小 | medium | 否 |
# options
属性 | 描述 | 必需 |
---|---|---|
title | 表单表头 | 是 |
key | 表单对应的字段 | 是 |
type | 控件类型 | 是 |
rules | 是否开启验证 | 否 |
# type
属性 | 描述 |
---|---|
input | 输入框 |
text | 文本输入框 |
switch | 开关 |
time | 时间 |
date | 日期 |
datetime | 日期时间 |
date-to-date | 开始日期 — 结束日期 |
datetime-to-datetime | 开始日期时间 — 结束日期时间 |
number | 数字 |
select | 选择框 |
radio | 单选框 |
checkbox | 多选框 |
checkbox绑定字段的值一定要是: []
例如:checkbox: []
# option
只有在
type
为[select, radio, checkbox]
时才需要设置
属性 | 描述 | 必需 |
---|---|---|
data | 数据源 | 是 |
Key | 指定key对应data的唯一字段 | 是 |
label | 指定label对应data的显示标题字段 | 是 |
value | 指定value对应data的值字段 | 是 |
# 方法
属性 | 描述 | 回调函数 |
---|---|---|
@onSearch | 搜索事件 | form |
# 效果图
# 更多表单
<template>
<div>
<div>
<MyForm
:form="formData.form"
:options="formData.options"
:rules="formData.rules"
:labelWidth="formData.labelWidth"
>
</MyForm>
<el-divider></el-divider>
</div>
</div>
</template>
<script>
import MyForm from "@/components/Form.vue";
export default {
name: "home",
components: {
MyForm
},
data() {
return {
formData: {
form: {
input: "",
text: "",
switch: true,
time: "10:10:10",
date: "2021-04-27",
datetime: "2021-04-27 10:10:10",
"date-to-date": "",
"datetime-to-datetime": "",
number: 0,
select: "",
radio: "",
checkbox: []
},
options: [
{
title: "输入框",
key: "input",
type: "input"
},
{
title: "文本",
key: "text",
type: "text"
},
{
title: "开关",
key: "switch",
type: "switch"
},
{
title: "时间",
key: "time",
type: "time"
},
{
title: "日期",
key: "date",
type: "date"
},
{
title: "日期时间",
key: "datetime",
type: "datetime"
},
{
title: "开始日期 --- 结束日期",
key: "date-to-date",
type: "date-to-date"
},
{
title: "开始日期时间 --- 结束日期时间",
key: "datetime-to-datetime",
type: "datetime-to-datetime"
},
{
title: "数字",
key: "number",
type: "number"
},
{
title: "选择框",
key: "select",
type: "select",
option: {
data: [
{
id: 1,
title: "女",
type: 0
},
{
id: 2,
title: "男",
type: 1
}
],
key: "id", // 指定key对应data的字段
label: "title", // 指定label对应data的字段
value: "type" // 指定value对应data的字段
}
},
{
title: "单选框",
key: "radio",
type: "radio",
option: {
data: [
{
id: 1,
title: "女",
type: 0
},
{
id: 2,
title: "男",
type: 1
}
],
key: "id", // 指定key对应data的字段
label: "title", // 指定label对应data的字段
value: "type" // 指定value对应data的字段
}
},
{
title: "多选框",
key: "checkbox",
type: "checkbox",
option: {
data: [
{
id: 1,
title: "1"
},
{
id: 2,
title: "2"
},
{
id: 3,
title: "3"
}
],
key: "id", // 指定key对应data的字段
label: "title" // 指定label对应data的字段
}
}
],
rules: {},
labelWidth: "250px"
}
};
},
mounted() {},
methods: {}
};
</script>
<style></style>
# 效果图
转载:https://blog.csdn.net/weixin_42863549/article/details/116167827
查看评论