基于element-plus封装通用型表单组件

在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组件,可以很方便的实现表单数据的输入、编辑等操作,大大简化表单页面的开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值