Vue 项目封装表单类型组件(ElementUi)

Vue 项目封装表单类型组件 iform.vue

当我们在做Vue项目时,有时候项目很大,页面功能比较多时,很多控件堆在一起,很是臃肿,管理起来很麻烦。因此,我们就需要封装一些组件,达到简洁高效、可复用的效果。本章节主要是介绍如何封装表单类型的组件。

封装表单类型组件需要用到的文件以及其他组件(重要)

1、i-input.vue 公用组件,是i-form组件的最重要的组件,主要封装的就是这个,i-form就是将i-input组件套了一层外壳(el-form)。因此,总的来说,是我们这章节主要封装的对象。

2、publicform.js 文件,这个文件就是一些封装组件的方法,文件里面定义了几种表单类型(input、select、selects、date、time、combogrid、combopanel、switch、input_number、input_numbers)。

3、myPublicForm i-input封装组件里面注册的子组件,是需要渲染的基础表单子组件,因为当我们publicform.js 文件返回给组件的是一大串html的字符串,如果直接使用 html属性渲染 那一大串html字符串时,是渲染不出来的,为什么呢?因为我这里vue项目使用了ElementUi框架,直接使用 html属性渲染是渲染不出来Elementui的各种标签的。因此,我们需要使用注册的子组件来渲染Elementui字符串。

一、publicform.js 文件的实现

// 封装基础组件框架
const getBaseElem = function(elem, opt) {
    let baseOptions = {
        type: '',
        model: '',
        placeholder: '',
        value: ''
    };
    var publicFrom = {
        input: function (attr) {
            if (attr) {
                let elemetOptions = getElement(attr);
                if (elemetOptions) {
                    var input = '<el-input' + elemetOptions + '></el-input>';
                    return input;
                } else {
                    return '<el-input></el-input>';
                }
            } else {
                
            }
        },
        select: function (attr, isMultiple) {
            if (!attr.option) {
                let elemetOptions = getElement(attr);
                if (elemetOptions) {
                    var select = '<el-select' + elemetOptions + '></el-select>';
                    return select;
                } else {
                    return '<el-select></el-select>';
                }
            } else {
                let elemetOptions = getElement(attr);
                if (elemetOptions) {
                    let multiple = isMultiple ? ' multiple ' : '';
                    var select = '<el-select' + elemetOptions + '' + multiple + '>';
                    attr.option.forEach(item => {
                        let elemetOptions = getElement(item);
                        select += '<el-option ' + elemetOptions + '></el-option>'
                    })
                    select += '</el-select>';
                    return select;
                } else {
                    return '<el-select></el-select>';
                }
            }
        },
        selects: function (attr) {
            return this.select(attr, true)
        },
        date: function (attr) {
            let elemetOptions = getElement(attr);
            if (elemetOptions) {
                var date = '<el-date-picker' + elemetOptions + '></el-date-picker>';
                return date;
            } else {
                return '<el-date-picker></el-date-picker>';
            }
        },
        time: function (attr) {
            let elemetOptions = getElement(attr);
            if (elemetOptions) {
                var time = '<el-time-picker' + elemetOptions + '></el-time-picker>';
                return time;
            } else {
                return '<el-time-picker></el-time-picker>';
            }
        },
        combogrid: function (attr) {
            if (attr) {
                let elemetOptions = JSON.stringify(attr);
                if (elemetOptions) {
                    var input = "<icombogrid ref='combogrid' :getOptions='"+elemetOptions+"'></icombogrid>";
                    return input;
                } else {
                    return '<icombogrid></icombogrid>';
                }
            } else {
                
            }
        },
        combopanel: function (attr) {
            if (attr) {
                let elemetOptions = JSON.stringify(attr);
                if (elemetOptions) {
                    var input = "<icombopanel :getOptions='"+elemetOptions+"'></icombopanel>";
                    return input;
                } else {
                    return '<icombopanel></icombopanel>';
                }
            } else {
                
            }
        },
        switch: function (attr) {
            let elemetOptions = getElement(attr);
            if (elemetOptions) {
                var time = '<el-switch' + elemetOptions + ' active-color="#13ce66"></el-switch>';
                return time;
            } else {
                return '<el-switch></el-switch>';
            }
        },
        input_number: function (attr) {
            let elemetOptions = getElement(attr);
            if (elemetOptions) {
                var time = '<el-input-number' + elemetOptions + ' controls-position="right"></el-input-number>';
                return time;
            } else {
                return '<el-input-number></el-input-number>';
            }
        },
        input_numbers: function (attr) {
            let array = {};
            let elemetOptions = getElement(attr);
            if (elemetOptions) {
                let time = '<div ' + elemetOptions + '>';
                attr.numbers.forEach((item) => {
                    array = Object.assign({}, array, item);
                    let arrayElem = getElement(array);
                    time += '<el-input-number' + arrayElem + ' controls-position="right"></el-input-number>';
                });
                time += '</div>'
                return time;
            } else {
                return '<el-input-number></el-input-number>';
            }
        }
    };
    return publicFrom[elem](opt)
},
// 解析对象键值对成属性
getElement = function (attr) {
    var v = 'v-',
        el = 'el-',
        typeV = ["model", "if", "show", "for"],
        elemHas = ["type", "model", "placeholder", "value", "style", "label", "name"]; // 通用属性
    if (attr) {
        var attrString = '',
            attrElement = '';
        for (var key in attr) {
            elemHas.forEach(item => {
                if (key == item) {
                    if (key == "model") {
                        attrString = v + key + '=' + '"' + attr[key] + '"';
                        attrString = attrString.toString()
                        attrElement += ' ' + attrString + ' ';
                    } else {
                        attrString = key + '=' + '"' + attr[key] + '"';
                        attrString = attrString.toString()
                        attrElement += ' ' + attrString + ' ';
                    }
                }
            })
        }
        return attrElement;
    } else {
        throw new Error("attr属性必须有值!");
    }
}
export default getBaseElem

二、i-input组件的实现

template 只需要一个子组件

<template>
    <div>
        <myPublicForm ref="myPublicForm"></myPublicForm>
    </div>
</template>

script 注册子组件,并且引入publicform文件,然后再渲染到子组件里。

<script>
import publicform from '../modules/publicForm.js' // 引入公共表单组件
import {EventBus} from '../modules/event-bus.js' // 引入事件总线
import Vue from 'vue';
export default {
    components: { // 需要渲染的基础表单子组件
        myPublicForm: {
            props: {
                showInputElem: {
                    type: String,
                    default: '<div></div>'
                },
                formData: {
                    type: Object,
                    default: () => {
                        return {}
                    }
                },
            },
            mounted() {
            },
            watch: {
            },
            render(h) { // -----------------------渲染--------最重要的部分---------
                const that = this
                const com = Vue.extend({
                    data() {
                        return {
                            rightFormData: that.newformData,
                        }
                    },
                    template: that.newShowInputElem,
                    mounted() {
                    	// 判断有没有combogrid的属性
                        this.$refs.hasOwnProperty("combogrid") && (that.combogrid = this.$refs.combogrid);
                    },
                });
                return h(com, {});
            },
            data() {
                return {
                    newShowInputElem: this.showInputElem,
                    newformData: this.formData,
                    combogrid:{}
                }
            }
        }
    },
    props: {
        formTypeValue: {
            type: Object,
            default: () => {
                return {}
            }
        },
        rightFormData: {
            type: Object,
            default: () => {
                return {}
            }
        }
    },
    watch: {
        rightFormData: {
            deep: true,
            handler (newValue) {
                // console.log('rightform', newValue)
                this.$refs.myPublicForm.newformData = this.rightFormData
            }
        }
    },
    data() {
        return {
        }
    },
    mounted() {
        this.getinputElem();
    },
    methods: {
        getinputElem() { // 渲染
            this.$refs.myPublicForm.newformData = this.rightFormData;
            if (this.formTypeValue.hasOwnProperty('elem')) {
                let arr = '';
                arr = publicform(this.formTypeValue.elem, this.formTypeValue);
                this.$refs.myPublicForm.newShowInputElem = arr;
            }
        },
        disappear() { // 清除
            this.$refs.myPublicForm.combogrid.hasOwnProperty("disappear") && this.$refs.myPublicForm.combogrid.disappear();
        }
    }
}
</script>

style

<style lang="scss">
    .el-table__row .el-input {
        width: 100%;
        .el-input__inner {
            height: 100%;
        }
    }

</style>

三、i-form组件的实现

i-form 组件就比较简单,主要的工作就是将 i-input 包上一层
< el-form>
< el-form-item>**************< /el-form-item>
</ el-form>

template

<template>
    <div :model="model" class="i-form">
        <el-form :inline="true" class="demo-form-inline">
            <el-form-item :label="item.label" v-for="(item, index) in formTypeValue" :key="index">
                <iinput  :ref="'input_'+index" :formTypeValue="item" :rightFormData="rightFormData"></iinput>
            </el-form-item>
        </el-form>
        <slot></slot>
    </div>
</template>

script

<script>
import publicform from '../modules/publicForm.js' // 引入公共表单组件
import {EventBus} from '../modules/event-bus.js' // 引入事件总线
import Iinput from '../allPage/i-input.vue';
import Vue from 'vue';
export default {
    name: 'i-form',
    components: {Iinput},
    props: {
        model: { // model
            type: Object,
            default: () => {
                return {}
            }
        },
        rightFormData: { // 父级传的或者自己默认的model值
            type: Object,
            default: () => {
                return {}
            }
        },
        formTypeValue: { // 父级传的或者自己默认的表单集合
            type: Array,
            default: () => {
                return []
            }
        },
        timeValue: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
        }
    },
    watch: {
        rightFormData: {
            deep: true,
            handler(newValue) {
                console.log('form', newValue)
            }
        }
    },
    mounted() {
    },
    methods: {
        disappear() { // 清除
            this.formTypeValue.forEach((item,index) => {
                var key = `input_${index}`;
                this.$refs[key][0].disappear();
            });
        },
    }
}
</script>

style

<style lang="scss">
    .i-form {
        padding: 0 10px; 
        display: flex;
        align-items: center;
        .el-button {
            height: 30px;
        }
    }
    .el-input {
        width: 200px;
        height: 30px;
    }
    .el-form--inline .el-form-item {
        margin-right: 30px;
        margin-bottom: 0px;
    }
</style>

End ~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值