1. 封装组件DymanicForm.vue
- 使用
component
实现动态组件 - 组件不能直接使用字符串传入,所以根据传入的组件名称找到对应的组件
- 校验规则,可使用rule传入自定义规则,也可以使用封装好的基本规则 示例中使用了
checkRequired
- 暴露重置方法和校验方法
<template><el-form:model="currentValue"ref="dymanicForm"v-bind="$attrs"@submit.native.prevent><el-form-item:prop="index":rules="item.rules"v-for="(item, index) in currentSchema":key="index"v-bind="item.formItem || {}"><componentv-model="currentValue[index]":is="item.componentName"v-bind="item"v-on="item.methods || {}"/></el-form-item><slot /></el-form>
</template><script lang="ts" setup>
import checkValidator from "~/utils/validator/index";import {ElInput,ElSelect,ElDatePicker,ElCheckbox,ElRadio,ElRadioGroup,ElCheckboxGroup,ElSwitch,
} from "element-plus";const componentMap = {ElInput: ElInput,ElSelect: ElSelect,ElDatePicker: ElDatePicker,ElCheckbox: ElCheckbox,ElRadio: ElRadio,ElRadioGroup: ElRadioGroup,ElCheckboxGroup: ElCheckboxGroup,
};const props = defineProps({schema: Object,modelValue: [String, Number, Boolean, Array, Date, Object],
});
const emit = defineEmits(["update:modelValue"]);
const currentValue = computed({get: () => props.modelValue,set: (val) => emit("update:modelValue", val),
});const currentSchema = computed(() => {const schema = {};for (const key in props.schema) {let { visible = true, ...item } = props.schema[key];// 动态表单的组件名item.componentName = componentMap[item.componentName];// 是否显示visible =typeof visible !== "function" ? visible : visible(currentValue, item);if (visible) {schema[key] = { clearable: true, ...item };}// 表单验证规则if (schema[key].validator && schema[key].validator.length) {if (!schema[key].rules) schema[key].rules = [];schema[key].validator?.forEach(([valida, args]) => {if (checkValidator[valida]) {schema[key].rules.unshift(checkValidator[valida](args));}});}}return schema;
});
const dymanicForm = ref(null);
const validate = (func) => {if (typeof func === "function") {dymanicForm.value.validate((valid) => {func(valid);});} else {return new Promise((resolve) => {dymanicForm.value.validate((valid) => {resolve(valid);});});}
};
const resetFields = () => {dymanicForm.value.resetFields();
};defineExpose({resetFields,validate,
});
</script>
2. 调用组件示例
<template><div class=""><DymanicFormref="formRef":inline="true":schema="schema"v-model="searchValue"><el-form-item><el-button type="primary" @click="handleQuery">查询</el-button><el-button @click="handleReset">重置</el-button></el-form-item></DymanicForm></div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
import type { ItemSchema } from "~/types/dymanic";
import DymanicForm from "~/components/DymanicForm.vue";const formRef = ref<InstanceType<typeof DymanicForm>>();
const schema = ref<ItemSchema>({userId: {formItem: {label: "用户ID:",},style: {width: "200px",},componentName: "ElInput",placeholder: "请输入用户ID",maxlength: 20,validator: [["checkRequired",{msg: "用户ID不能为空",},],],},username: {formItem: {label: "账号:",},style: {width: "200px",},componentName: "ElInput",placeholder: "请输入账号",maxlength: 20,},name: {formItem: { label: "用户名:" },style: {width: "200px",},componentName: "ElInput",placeholder: "请输入用户名",maxlength: 20,},
});
const searchValue = reactive({userId: "",username: "",name: "",
});
const handleQuery = () => {formRef.value.validate((valid: boolean) => {if (valid) {console.log("查询", searchValue);// 查询逻辑}});
};const handleReset = () => {formRef.value.resetFields();
};
</script>
<style lang="scss" scoped></style>
3. 校验规则示例
// 校验内容不能为空的验证
const checkRequired = ({ msg, trigger = ['blur'] }) => {return {required: true,message: msg,trigger,}
}export default checkRequired