在vue开发时很讨厌写表单,感觉好麻烦。这里基于element-plus封装通用型表单组件,只需要提供表单数据即可,自己感觉比较不错……
一、创建组件FormSubmit.vue
<template>
<div class="form-box">
<el-form
label-width="120px"
:model="formData"
ref="form"
:rules="rules"
:inline="false"
size="default"
:label-position="label"
style="max-width: 1000px"
>
<el-form-item
v-for="(value, key) in formData"
:label="value.label"
:prop="key"
>
<el-input
v-if="value.type === 'input'"
v-model="formData[key].value"
:placeholder="formData[key].description || '请输入'"
></el-input>
<el-input
v-else-if="value.type === 'textarea'"
type="textarea"
:placeholder="formData[key].description || '请输入'"
v-model="formData[key].value"
></el-input>
<el-input
v-else-if="value.type === 'password'"
type="password"
placeholder="请输入用户密码"
v-model="formData[key].value"
></el-input>
<el-select
v-else-if="value.type === 'select'"
v-model="value.value"
:placeholder="formData[key].description || '请选择'"
>
<el-option
v-for="item in formData[key].option"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-radio-group
v-else-if="value.type === 'radio'"
v-model="value.value"
>
<el-radio
v-for="item in formData[key].option"
:key="item.value"
:value="item.value"
>{{ item.label }}</el-radio
>
</el-radio-group>
<el-checkbox-group
v-else-if="value.type === 'chackbox'"
v-model="value.value"
>
<el-checkbox
v-for="item in formData[key].option"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-checkbox-group>
<el-date-picker
v-else-if="value.type === 'datepicker'"
v-model="value.value"
type="datetime"
placeholder="请选择日期时间"
/>
<!-- 自动补全 -->
<el-autocomplete
v-else-if="value.type === 'autocomplete'"
@select="onSelect"
v-model="formData[key].value"
:fetch-suggestions="querySearch"
clearable
:placeholder="formData[key].description || '请选择'"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交数据</el-button>
<el-button @click="cancel">取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
const form = ref();
const props = defineProps({
formData: {
type: Object,
default: () => ({}),
},
rules: {
type: Object,
default: () => ({}),
},
label: "right",
id: "",
});
const emit = defineEmits(["submit", "onCancel", "onSelect"]);
// 获取自动补全数据
onMounted(() => {
for (let key in props.formData) {
if (props.formData[key].type === "autocomplete") {
restaurants.value = props.formData[key].option;
}
}
});
const restaurants = ref([]);
// 自动补全
const querySearch = (queryString, cb) => {
const results = queryString
? restaurants.value.filter(createFilter(queryString))
: restaurants.value;
// 回调函数 返回建议列表
cb(results);
};
const createFilter = (queryString) => {
return (restaurant) => {
return (
restaurant.value
.toLowerCase()
.indexOf(queryString.toLowerCase()) === 0
);
};
};
const onSelect = (item) => {
emit("onSelect", item);
};
const onSubmit = () => {
form.value.validate((valid) => {
if (valid) {
let formValue = {};
// 获取表单value
for (const key in props.formData) {
if (
props.formData[key].type === "chackbox" &&
props.formData[key].value.length > 0
) {
formValue[key] = [...props.formData[key].value]; //chackbox的值是数组类型
} else {
formValue[key] = props.formData[key].value; //其余的都是非数组
}
}
emit("submit", { formValue, id: props.id });
} else {
console.log("error submit!!");
return false;
}
});
};
function cancel() {
emit("onCancel");
form.value.resetFields();
}
</script>
<style scoped>
.form-box {
margin: 0 auto;
margin-top: 30px;
}
</style>
这样就封装好了一个组件,在页面直接用就好了!
二、在页面引用
引用的主要代码如下:
<template>
<FormSubmit
:formData="formDataEdit"
:rules="rules"
:id="formID"
@submit="onSubmitAdd"
@onCancel="onCancelAdd"
@onSelect="onSelectCompany"
/>
</template>
<script setup>
import FormSubmit from "@/components/FormSubmit.vue";
import { ref } from "vue";
// 新增表单数据
const formDataAdd = ref({
title: {
type: "input",
value: "",
label: "标题",
description: "请输入项目的标题",
},
description: {
type: "textarea",
value: "",
label: "内容简介",
description: "请输入详细的介绍",
},
createdAt: {
type: "datepicker",
value: "",
label: "创建时间",
},
province: {
type: "chackbox",
value: [],
label: "省份",
option: [
{
label: "贵州省",
value: "gzs",
},
{
label: "四川省",
value: "scs",
},
{
label: "云南省",
value: "yns",
},
{
label: "重庆市",
value: "cqs",
},
],
},
sex: {
type: "radio",
value: "woman",
label: "性别",
option: [
{
label: "男",
value: "man",
},
{
label: "女",
value: "woman",
},
],
},
company: {
type: "autocomplete",
value: "",
label: "公司",
option: [
{
custom: "http://www.qq.com",
value: "腾讯公司",
},
{
custom: "http://www.ali.com",
value: "阿里公司",
},
{
custom: "http://www.baidu.com",
value: "百度公司",
},
],
},
});
// 编辑表单数据
const formDataEdit = ref({
title: {
type: "input",
value: "这是项目标题",
label: "标题",
description: "请输入项目的标题",
},
description: {
type: "textarea",
value: "这是内容简介",
label: "内容简介",
description: "请输入详细的介绍",
},
createdAt: {
type: "datepicker",
value: "2024-07-14",
label: "创建时间",
},
province: {
type: "chackbox",
value: ["gzs", "cqs"],
label: "省份",
option: [
{
label: "贵州省",
value: "gzs",
},
{
label: "四川省",
value: "scs",
},
{
label: "云南省",
value: "yns",
},
{
label: "重庆市",
value: "cqs",
},
],
},
sex: {
type: "radio",
value: "woman",
label: "性别",
option: [
{
label: "男",
value: "man",
},
{
label: "女",
value: "woman",
},
],
},
company: {
type: "autocomplete",
value: "阿里公司",
label: "公司",
option: [
{
custom: "http://www.qq.com",
value: "腾讯公司",
},
{
custom: "http://www.ali.com",
value: "阿里公司",
},
{
custom: "http://www.baidu.com",
value: "百度公司",
},
],
},
});
// 表单对应记录ID
const formID = ref("");
// 表单数据校验规则
const rules = ref({
title: [{ required: true, message: "请输入文章标题", trigger: "blur" }],
// province: [{ required: true, message: "请选择省份", trigger: "blur" }],
});
// 提交数据
function onSubmitAdd(params) {
console.log("提交数据", params);
}
// 选择下拉框
function onSelectCompany(item) {
console.log("选择下拉框", item);
}
// 取消提交
function onCancelAdd() {
console.log("取消提交");
}
</script>
在代码中,我列了两个数据formDataEdit 、formDataAdd只需要提供一个即可,其实区别就是前者value有初始值,可以作为编辑表单使用,后者value没有初始值,可作为新增表单使用。
需要注意:不允许出现两个或两个以上的自动补全下拉框。
效果如下:
如果结合element-plus的el-dialog组件,可以很方便的实现表单数据的输入、编辑等操作,大大简化表单页面的开发。