Vue-表单组件

发布时间 2023-11-17 16:28:06作者: 忙着可爱呀~

组件代码:

<!-- 
    * @Descripttion:表单组件-->
<template>
    <div class='YxkForm'>
        <el-form :model="form" :ref="$attrs.formRef || 'ruleForm'" v-bind="formBind(formObj)">
            <!-- 表单项 -->
            <el-form-item v-for="(item, index) in formObj.list" :key="index" v-bind="formItemBind(item)">
                <FormItem :form="form" :params="item" :selectOptions="selectOptions">
                    <template v-slot:[item.slots]="scope">
                        <slot :name="item.slots" :scope="{...scope, $index: index}"></slot>
                    </template>
                </FormItem>
                <!-- 提示 -->
                <template>
                    <div v-if="item.attrs && item.attrs.tip" class="color__danger">{{item.attrs.tip}}</div>
                </template>
            </el-form-item>
            <!-- 表单按钮 -->
            <template v-if="!formObj.hideButton">
                <el-form-item>
                    <FormButton v-for="item in formObj.button" :key="item.text" :params="item">
                        <template v-slot:text="scope">{{scope.text}}</template>
                    </FormButton>
                </el-form-item>
            </template>
        </el-form>
    </div>
</template>

<script>
    // render渲染
    const FormItem = {
        props: {
            form: {
                type: Object
            },
            params: {
                type: Object
            },
            selectOptions: {
                type: Object
            }
        },
        render(createElement) {
            // 选择项
            const options = (params, list) => {
                // 属性
                let item = JSON.parse(JSON.stringify(list))
                let props = {
                    attrs: {
                        ...item
                    },
                    domProps: {},
                    children: []
                }
                // 属性key值
                if (params.keys) {
                    for (let key in params.keys) {
                        props.attrs[key] = item[params.keys[key]]
                        if (key == 'text') {
                            item.text = item[params.keys[key]]
                        }
                    }
                }
                this.selectOptions.list.map(list => {
                    if (params.ele == list.ele) props.ele = list.child // 选择项-元素
                    if (this.selectOptions.type.indexOf(params.ele) != -1) { // 选择项-文本
                        props.children = [{
                            ele: 'span',
                            domProps: {
                                innerHTML: item.text
                            }
                        }]
                    }
                })
                // 删除附属属性
                if (item.id !== undefined) delete props.attrs.id
                if (item.text) delete props.attrs.text
                return createNode(props)
            }
            const createNode = params => {
                // ele 元素
                let ele = params.ele
                // 参数
                let props = {
                    attrs: {
                        ...params.attrs
                    },
                    class: params.class,
                    style: params.style,
                    domProps: {
                        ...params.domProps
                    },
                    on: {}
                }
                // v-model绑定
                if (params.model && !params.slots) {
                    props.attrs.value = this.form[params.model]
                    props.on = {
                        input: e => {
                            this.$set(this.form, params.model, e)
                        }
                    }
                }
                // 事件
                if (params.on) {
                    Object.assign(props.on, params.on)
                }
                // 子元素
                let childNodes = []
                if (params.children) {
                    childNodes = params.children.map(item => {
                        return createNode(item)
                    })
                }
                if (params.options) { // 子元素-选择项
                    childNodes = params.options.map(item => {
                        return options(params, item)
                    })
                }
                // slot
                if (params.slots) {
                    childNodes.push(this.$scopedSlots[params.slots](params))
                }
                return createElement(ele, props, childNodes)
            }
            return createNode(this.params)
        },
    }
    // 按钮
    const FormButton = {
        props: {
            params: {
                type: Object
            }
        },
        render(createElement) {
            const createNode = params => {
                // ele 元素
                let ele = params.ele || 'el-button'
                // 属性
                let attrs = JSON.parse(JSON.stringify(params))
                if (attrs.text) delete attrs.text
                if (attrs.click) delete attrs.click
                let props = {
                    attrs: {
                        ...attrs
                    },
                    on: {}
                }
                // 事件
                if (params.click) {
                    props.on.click = params.click
                }
                // 子元素
                let childNodes = []
                childNodes.push(this.$scopedSlots.text(params))
                return createElement(ele, props, childNodes)
            }
            return createNode(this.params)
        },
    }

    export default {
        name: 'YxkForms',
        componentName: 'YxkForms',
        props: {
            formObj: {
                type: Object,
                default: () => {
                    return {
                        button: []
                    }
                }
            },
            form: {
                type: Object
            }
        },
        components: {
            FormItem,
            FormButton
        },
        data() {
            return {
                selectOptions: {}
            }
        },
        methods: {
            // v-bind
            formBind(obj) {
                if (!obj.button) {
                    this.formObj.button = [{
                        text: '保存',
                        type: "primary",
                        click: () => this.submit()
                    }]
                }
                return Object.assign({
                    size: "medium",
                    'label-width': '120px'
                }, this.$attrs)
            },
            formItemBind(obj) {
                return Object.assign({
                    prop: obj.model
                }, this.deleteParams(obj, ['ele', 'model', 'attrs', 'domProps', 'slots', 'children']))
            },
            // delete params
            deleteParams(obj, arr) {
                let params = JSON.parse(JSON.stringify(obj))
                arr.forEach(item => {
                    delete params[item]
                })
                return params
            },
            // 默认提交
            submit() {
                this.$emit('submit')
            },
            // 初始化
            initialSet() {
                this.selectOptions = {
                    list: [{ // 选择项
                        ele: 'el-radio-group',
                        child: 'el-radio'
                    }, {
                        ele: 'el-checkbox-group',
                        child: 'el-checkbox'
                    }, {
                        ele: 'el-select',
                        child: 'el-option'
                    }],
                    type: ['el-radio-group', 'el-checkbox-group'] // 特殊处理选择项
                }
            }
        },
        computed: {},
        watch: {},
        created() {
            this.initialSet()
        },
        mounted() {}
    }
</script>

<style lang='scss'>
    .YxkForm {
        padding: 20px;
        background: #fff;

        .color__danger {
            color: red;
            font-size: 12px;
        }
    }
</style>

示例:

 

 

参数说明:

YxkForms

 

 

formObj

 

 

formObj.list

 

 

formObj.button