当前位置: 首页 > article >正文

vue3中使用render函数以及组合式写法实现一个配置化生成的表单组件

表单组件代码

import { h, computed, ref } from 'vue'
import type { PropType } from 'vue'
import { Form, Input, Radio, FormItem, Checkbox } from '@arco-design/web-vue'

//去除定义类型中 指定的key
type RestrictKey<T, K extends keyof any> = {
  [P in keyof T]: P extends K ? never : T[P];
};

//FormPropsType 类型中的属性与官网form 组件的属性保持一致 但不用再声明model属性
export type FormPropsType =RestrictKey<{
  model?: string; 
  items: {
    [key: string]: {
        type: 'radio' | 'input' | 'checkbox' | 'slot'
        //config 类型中的属性与官网formItem 组件的属性保持一致 但不用再声明field属性
        config: RestrictKey<{
          [key: string]: any;
          field?: string; 
      },'field'> //去除field属性 不允许传model属性
        slotFormConfig: {
            modelValue: any
            [key: string]: any
        }
    }
}
  [key: string]: any
},'model'> //去除model属性 不允许传model属性

export default {
    components: {
        Form,
        Input,
        Radio,
        FormItem,
        Checkbox
    },
    props: {
        config: {
            type: Object as PropType<FormPropsType>
        }
    },
    setup(props: FormPropsType, { expose, emit, slots }: any) {
        const FormRef = ref()

        //渲染表单项组件
        const formItemComponent = computed(() => {
            return Array.from(Object.keys(props.config.items)).map(formItemName => {
                const formItemConfig = props.config.items[formItemName]
                formItemConfig.slotFormConfig['onUpdate:modelValue'] = (e:any) => {
                    // emit('onUpdate:modelValue', e)
                    formItemConfig.slotFormConfig.modelValue = e
                }
                formItemConfig.config['field'] = formItemName
                let slotComp
                switch (formItemConfig.type) {
                    case 'slot':
                        slotComp = h(
                            'div',
                            {
                              style:{
                                width:'100%',
                                height:'100%'
                              }
                            },
                            slots[formItemName](props.config.items[formItemName].slotFormConfig)
                        )
                        break
                    case 'input':
                        slotComp = h(Input, props.config.items[formItemName].slotFormConfig)
                        break
                    case 'radio':
                        slotComp = h(Radio, props.config.items[formItemName].slotFormConfig)
                        break
                    case 'checkbox':
                        slotComp = h(Checkbox, props.config.items[formItemName].slotFormConfig)
                        break
                }
                const comp = h(FormItem, formItemConfig.config, slotComp)
                return comp
            })
        })

        //渲染表单组件
        const formComponent = computed(() => {
            return h(
                Form,
                {
                    ...props.config,
                    model: Object.keys(props.config.items)
                        .map(formItemName => {
                            return [
                                formItemName,
                                props.config.items[formItemName].slotFormConfig.modelValue
                            ]
                        })
                        .reduce((acc: any, [key, value]) => {
                            acc[key] = value
                            return acc
                        }, {}),
                    ref: FormRef
                },
                formItemComponent.value
            )
        })

        expose({
            FormRef
        })
        return () => h('div', {}, formComponent.value)
    }
}

示例代码

<script setup lang="ts">
import { ref } from 'vue'
import XForm from '@/components/common/x-form/index.ts'
import type { FormPropsType } from '@/components/common/x-form/index.ts'
import { defineEmits } from 'vue'
let emit = defineEmits(['update:selectedKeys'])






const xFormRef=ref()
const formConfig = ref<FormPropsType>({
    items: {
        name: {
            type: 'slot',
            config: {
                label: '姓名',
                rules: [{ required: true, message: 'Name is required' }],
                style:{
                  width:'300px'
                }
            },
            slotFormConfig: {
                modelValue: ''
            }
        }
    }
})

function verifyForm() {
  xFormRef.value.FormRef.validate()

}
</script>

<template>
    <XForm :config="formConfig" ref="xFormRef">
        <template #name="scoped">
            <a-input v-model="scoped.modelValue" />
        </template>
    </XForm>
    <a-button type="primary" @click="verifyForm">校验</a-button>

</template>

<style scoped></style>


http://www.kler.cn/a/515253.html

相关文章:

  • 数论问题61一一各种进位制
  • leetcode hot100(3)
  • 1561. 你可以获得的最大硬币数目
  • Qt实践:一个简单的丝滑侧滑栏实现
  • Java 大视界 -- 深度洞察 Java 大数据安全多方计算的前沿趋势与应用革新(52)
  • 在Debian系统中安装Debian(Linux版PE装机)
  • 正向代理与反向代理的主要区别
  • 极速、免费、体积小,一款PDF转图片软件
  • 微信小程序1.1 微信小程序介绍
  • leetcode——轮转数组(java)
  • leetcode_字符串 409. 最长回文串
  • 什么是IP地址、子网掩码、网关、DNS
  • AI刷题-策略大师:小I与小W的数字猜谜挑战
  • Matlab 亥姆霍兹谐振器的吸声特性
  • 【机器学习应用】预处理与特征工程
  • 【PCL】Segmentation 模块—— 条件欧几里得聚类(Conditional Euclidean Clustering)
  • Redis vs. 其他数据库:深度解析,如何选择最适合的数据库?
  • cuda + cudnn安装
  • C语言 指针_野指针 指针运算
  • 【AI日志分析】基于机器学习的异常检测:告别传统规则的智能进阶