<!-- * @Description: 表单渲染器,根据json生成表单 --> <template> <div class="v-form-container"> <Form class="v-form-model" ref="eFormModel" :model="formModel" v-bind="formModelProps"> <Row> <FormRender v-for="(schema, index) of noHiddenList" :key="index" :schema="schema" :formConfig="formConfig" :formData="formModelNew" @change="handleChange" :setFormModel="setFormModel" @submit="handleSubmit" @reset="resetFields" > <template v-if="schema && schema.componentProps" #[`schema.componentProps!.slotName`]> <slot :name="schema.componentProps!.slotName" v-bind="{ formModel: formModel, field: schema.field, schema }" ></slot> </template> </FormRender> </Row> </Form> </div> </template> <script lang="ts"> import { computed, defineComponent, PropType, provide, ref, unref } from 'vue'; import FormRender from './components/FormRender.vue'; import { IFormConfig, AForm } from '../../typings/v-form-component'; import { Form, Row, Col } from 'ant-design-vue'; import { useFormInstanceMethods } from '../../hooks/useFormInstanceMethods'; import { IProps, IVFormMethods, useVFormMethods } from '../../hooks/useVFormMethods'; import { useVModel } from '@vueuse/core'; import { omit } from 'lodash-es'; export default defineComponent({ name: 'VFormCreate', components: { FormRender, Form, Row, }, props: { fApi: { type: Object, }, formModel: { type: Object, default: () => ({}), }, formConfig: { type: Object as PropType<IFormConfig>, required: true, }, }, emits: ['submit', 'change', 'update:fApi', 'update:formModel'], setup(props, context) { const wrapperComp = props.formConfig.layout == 'vertical' ? Col : Row; const { emit } = context; const eFormModel = ref<AForm | null>(null); const formModelNew = computed({ get: () => props.formModel, set: (value) => emit('update:formModel', value), }); const noHiddenList = computed(() => { return ( props.formConfig.schemas && props.formConfig.schemas.filter((item) => item.hidden !== true) ); }); const fApi = useVModel(props, 'fApi', emit); const { submit, validate, clearValidate, resetFields, validateField } = useFormInstanceMethods(props, formModelNew, context, eFormModel); const { linkOn, ...methods } = useVFormMethods( { formConfig: props.formConfig, formData: props.formModel } as unknown as IProps, context, eFormModel, { submit, validate, validateField, resetFields, clearValidate, }, ); fApi.value = methods; const handleChange = (_event) => { const { schema, value } = _event; const { field } = unref(schema); linkOn[field!]?.forEach((formItem) => { formItem.update?.(value, formItem, fApi.value as IVFormMethods); }); }; /** * 获取表单属性 */ const formModelProps = computed( () => omit(props.formConfig, ['disabled', 'labelWidth', 'schemas']) as Recordable, ); const handleSubmit = () => { submit(); }; provide('formModel', formModelNew); const setFormModel = (key, value) => { formModelNew.value[key] = value; }; provide<(key: String, value: any) => void>('setFormModelMethod', setFormModel); // 把祖先组件的方法项注入到子组件中,子组件可通过inject获取 return { eFormModel, submit, validate, validateField, resetFields, clearValidate, handleChange, formModelProps, handleSubmit, setFormModel, formModelNew, wrapperComp, noHiddenList, }; }, }); </script> <style lang="less" scoped> .v-form-model { overflow: hidden; } </style>