Vue3+Ts+Elementpuls--动态表单(根据配置项,动态生成表单)

这里使用的UI框架是ElementPlus,更换其他组件直接更换constant.ts中的type配置和对应的Form组件即可.
大家可以npm install elementplus_dy_form来体验。
思路:
1.这里需要使用h函数方便控制要渲染的表单
2.传递type作为组件或html元素进行渲染,
3.默认包一层El-form,每个数组项会包一个El formItem
4.传入formDataKey,对绑定的表单项进行映射
5.通过next函数决定渲染的表单,next函数接收参数即表单数据

建议配置unplugin-auto-impor插件

创建一个静态文件存放配置

import { type DyFormConfig } from '../components/DyForm/DyForm.'
import {ElButton,ElInput,ElCheckbox,ElSelect,ElOption,ElSwitch,ElCheckboxGroup,ElRadioGroup,ElRadio,ElCol,ElDatePicker} from 'element-plus'
export class UserForm {
    name?: string
    organization?: string
    date1?: string
    date2?: string
    delivery?: boolean
    type?: []
    resource?: string
    desc?: string
    personInfo?: string
    developerName?: string
    sponsorName?: string
}

export function useDyFormConfig(dyForm: any) {
    const DyFormConfig: DyFormConfig<UserForm>[] = [
        {
            type: ElInput,
            formItemConfig: {
                label: '请输入姓名',
            },
            formConfig: {
                placeholder: '请输入姓名',
            },
            formDataKey: 'name'
        },
        {
            type: ElSelect,
            formItemConfig: {
                label: '请选择组织',
            },
            formConfig: {
                placeholder: '请选择您的组织'
            },
            formDataKey: 'organization',
            children: [
                {
                    type: ElOption,
                    formConfig: { label: '个人', value: 'person' },

                },
                {
                    type: ElOption,
                    formConfig: { label: '公司', value: 'company' }
                },
                {
                    type: ElOption,
                    formConfig: { label: '无', value: 'none' }
                }
            ],
            next(formData) {
                if (formData.organization === 'none') {
                    return {
                        next() {
                            return {
                                type: ElInput,
                                formItemConfig: {
                                    label: '请输入您所属组织'
                                },
                            }
                        }
                    }
                } else if (formData.organization === 'company') {
                    return [
                        {
                            type: 'div',
                            formConfig: {
                                style: {
                                    width: '100%',
                                    display: 'flex'
                                }
                            },
                            formItemConfig: {
                                label: '请选择日期', 
                            },
                            children: [
                                {
                                    type: ElCol,
                                    formConfig: {
                                        span: 11
                                    },
                                    children: [
                                        {
                                            needFormItem: true,
                                            type: ElDatePicker,
                                            formDataKey: 'date1',
                                            formConfig: {
                                                type: "date",
                                                placeholder: "请选择进入公司日期",
                                                style: "width: 100%"
                                            },
                                        }
                                    ]
                                },
                                {
                                    type: ElCol,
                                    formConfig: {
                                        span: 2
                                    },
                                    children: [
                                        {
                                            type: 'span',
                                            children: '-'
                                        }
                                    ]
                                },
                                {
                                    type: ElCol,
                                    formConfig: {
                                        span: 11
                                    },
                                    children: [
                                        {
                                            needFormItem: true,
                                            type: ElDatePicker,
                                            formDataKey: 'date2',
                                            formConfig: {
                                                type: "date",
                                                placeholder: "请选择毕业日期",
                                                style: "width: 100%"
                                            },
                                        }
                                    ]
                                },

                            ],
                            next(formData) {
                                console.log(formData)
                                return [{
                                    type: ElInput,
                                    formItemConfig: {
                                        label: '请输入个人信息'
                                    },
                                    formConfig: {
                                        placeholder: '请输入个人信息'
                                    }
                                }]
                            }
                        },
                    ]
                } else {
                    return [{
                        type: ElInput,
                        formDataKey: 'personInfo',
                        formItemConfig: {
                            label: '请输入个人信息'
                        },
                        formConfig: {
                            placeholder: '请输入个人信息'
                        }
                    }]
                }

            }
        },
        {
            type: ElSwitch,
            formDataKey: 'delivery',
            formItemConfig: {
                label: 'Instant delivery',
            }
        },
        {
            type: ElCheckboxGroup,
            formDataKey: 'type',
            formItemConfig: {
                label: 'Activity type',
            },
            children: [
                { type: ElCheckbox, slots: { default: () => '活动1' }, formConfig: { name: 'type', label: '活动1' } },
                { type: ElCheckbox, slots: { default: () => '活动2' }, formConfig: { name: 'type', label: '活动2' } },
                { type: ElCheckbox, slots: { default: () => '活动3' }, formConfig: { name: 'type', label: '活动3' } },
                { type: ElCheckbox, slots: { default: () => '活动4' }, formConfig: { name: 'type', label: '活动4' } }
            ],

        },
        {
            type: ElRadioGroup,
            formDataKey: 'resource',
            formItemConfig: {
                label: 'Resources'
            },
            children: [
                {
                    type: ElRadio,
                    formConfig: {
                        label: 'Sponsor'
                    }
                },
                {
                    type: ElRadio,
                    formConfig: {
                        label: 'Developer'
                    }
                },
            ],
            next(formData) {
                const resource = formData.resource
                const obj = {
                    'Sponsor': [
                        {
                            type: ElInput,
                            formDataKey: 'sponsorName',
                            formItemConfig: {
                                label: '请输入赞助商名称'
                            },
                        }
                    ],
                    'Developer': [
                        {
                            type: ElInput,
                            formDataKey: 'developerName',
                            formItemConfig: {
                                label: '请输入开发商名称'
                            },
                        }
                    ],
                } as Record<string, DyFormConfig[]>
                if (!resource) {
                    return []
                } else {
                    return obj[resource]
                }
            },
        },
        {
            type: ElInput,
            formConfig: {
                type: 'textarea'
            },
            formDataKey: 'desc',
            formItemConfig: {
                label: 'Activity form',
            }
        },
        {
            type: 'div',
            formConfig: {
                style: {
                    width: "100%",
                    display: "flex"
                }
            },
            children: [
                {
                    type: ElCol,
                    formConfig: {
                        span: 6
                    },
                    children: [
                        {
                            type: ElButton,
                            formConfig: {
                                type: 'warning',
                                onClick: async () => {
                                    const formRef = dyForm!.value!.getFormRef()
                                    formRef.value.validate()
                                }
                            },
                            slots: {
                                default: () => '确认'
                            }
                        }
                    ]
                },
                {
                    type: ElCol,
                    formConfig: {
                        span: 18
                    },
                    children: [
                        {
                            type: ElButton,
                            formConfig: {
                                type: 'danger',
                                onClick: () => {
                                    const formRef = dyForm!.value!.getFormRef()
                                    formRef.value.resetFields()
                                }
                            },
                            slots: {
                                default: () => '取消'
                            }
                        }
                    ]
                }
            ]
        }
    ];
    return {
        DyFormConfig
    }
}

使用示例

<script setup lang="ts">
import {DyForm} from './components/Dyform/DyForm.ts';
import { useDyFormConfig, UserForm } from './utils/constant'
import {ref,reactive} from 'vue'

const dyForm = ref(null)
const { DyFormConfig }  = useDyFormConfig(dyForm)
const form = ref<UserForm>({
    name: '',
    organization: '',
    date1: '',
    date2: '',
    delivery: false,
    type: [],
    resource: '',
    desc: '',
    personInfo:''
});

const rules = {
  name: [
    { required: true, message: 'Please input Activity name', trigger: 'blur' },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ],
  region: [
    {
      required: true,
      message: 'Please select Activity zone',
      trigger: 'change',
    },
  ],
  delivery: [
    {
      required: true,
      message: 'Please select delivery',
      trigger: 'change',
    },
  ],
  organization: [
    {
      required: true,
      message: 'Please select organization',
      trigger: 'change',
    },
  ],
  date1: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a date',
      trigger: 'change',
    },
  ],
  date2: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a time',
      trigger: 'change',
    },
  ],
  type: [
    {
      type: 'array',
      required: true,
      message: 'Please select at least one activity type',
      trigger: 'change',
    },
  ],
  resource: [
    {
      required: true,
      message: 'Please select activity resource',
      trigger: 'change',
    },
  ],
  desc: [
    { required: true, message: 'Please input activity form', trigger: 'blur' },
  ],
}

const formConfig = reactive({
  labelWidth: '130px',
  rules
})

</script>

<template>
    <DyForm ref="dyForm" v-model="form" :dyFormConfig="DyFormConfig" :formConfig="formConfig" />
</template>

<style scoped>
#app,
html,
body {
    width: 100vw;
    height: 100vh;
}

</style>

结果展示:
在这里插入图片描述

表单数据精准绑定嵌套的复杂数据类型

下面数据中,如果我想更新form.info.address,组件支持吗?Yes

const form = ref<UserForm>({
    name: '',
    organization: '',
    date1: '',
    date2: '',
    delivery: false,
    type: [],
    resource: '',
    desc: '',
    personInfo:'',
    info:{
        address: "",
        job:""
    }
});

只需要配置formKey

 // ...
		{
            type: ElInput,
            formConfig: {
                type: 'textarea'
            },
            formDataKey: 'info.address', 这样配置就行了
            formItemConfig: {
                label: '住址',
            }
        },
// ...

请添加图片描述

示例二

我们想精准绑定test.user[0].age该怎么做?
在这里插入图片描述
非常简单,如下图所示配置即可。
在这里插入图片描述
看结果展示
请添加图片描述

注意

不是很建议表单嵌套十分复杂的数据类型,如果有这种需求建议打平,然后自己再组装,如果不追求性能忽略这条。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
要在Vue 3中使用Agent Vue和TypeScript(TS)进行跳转到详情页,你可以按照以下步骤操作: 1. 首先,确保你已经安装了Vue 3和Agent Vue。你可以使用npm或yarn进行安装: ``` npm install vue@next agent-vue ``` 或者 ``` yarn add vue@next agent-vue ``` 2. 在你的Vue组件中,首先导入Agent Vue的`useRouter`函数和相关的类型定义: ```typescript import { useRouter } from 'agent-vue'; import { RouteLocationNormalized } from 'vue-router'; ``` 3. 在组件中定义一个函数来处理跳转到详情页的逻辑。你可以使用`useRouter`函数获取路由实例,然后使用`push`方法进行跳转: ```typescript export default { // ... methods: { goToDetailPage() { const router = useRouter(); const detailRoute: RouteLocationNormalized = { name: 'detail', // 替换为你的详情页路由名称 params: { // 传递的参数 }, }; router.push(detailRoute); }, }, // ... }; ``` 4. 在模板中使用`goToDetailPage`方法来触发跳转事件。你可以在按钮点击事件或者其他需要跳转的地方调用该方法: ```html <template> <button @click="goToDetailPage">跳转详情页</button> </template> ``` 确保将`goToDetailPage`方法绑定到对应的事件上。 这样,当点击按钮时,页面将会跳转到你定义的详情页路由。 请注意,上述代码中的路由名称和参数是示例,请根据你的实际情况进行修改。另外,确保在Vue Router中配置了对应的详情页路由。 希望能帮到你!如果你还有其他问题,请随时提问。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鲤余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值