乐趣区

iview中-formtable-渲染的问题

描述

需求

在表格里面渲染 form 表单,数字保留 2 位小数,不足的自动补齐。

选用

选用的是 iview 的组件 Form、Input、Table。

Form 表单的数据可以双向绑定,这样在对输入的数据做补零操作后,更新 Form 表单的 model 绑定的数据,即可更新。

没有使用 InputNumber 是因为它的交互用户体验不是很友好,而选用了常用的 Input。
但问题不是出在这里,请继续往下看。

form+table

test.vue

<template>
    <div>
        <Form
                ref="formTable"
                :model="formTable"
                :rules="rulesTable"
                inline
        >
            <Table border :columns="columns" :data="data"></Table>
        </Form>
    </div>
</template>
<script>

   let Trim=function(str,isGlobal) {
        let result;
        result = str.replace(/(^\s+)|(\s+$)/g,"");
        if(isGlobal === true)
            result = result.replace(/\s/g,"");
        return result;
    };

    import FormItemInput from './form-item-input.vue';
    export default {
        name:'test',
        components: {FormItemInput},
        data() {
            return {
                //+++ form 表单 start
                formTable:{},
                rulesTable:{},
                //+++ form 表单 end
                // +++++++ table start
                data:[
                    {
                        "id":1,
                        "name":"张三",
                        "score":""
                    },
                    {
                        "id":2,
                        "name":"李四",
                        "score":""
                    }
                ],
                columns:[
                    {
                        title: '序号',
                        type: 'index',
                        width: 60,
                        align: 'center'
                    },
                    {
                        title: '姓名',
                        key: 'name',
                        width: 200,
                        ellipsis:true
                    },
                    {
                        title: '成绩',
                        key: 'score',
                        width: 150,
                        className:'custom-table-form',
                        ellipsis:true,
                        renderHeader:(h, params) => {
                            // 2019 年 1 月 4 日 11:01:36
                            // 必填 需要展示 *
                            return h('div', [
                                h('i', {
                                    style: {
                                        color: 'red',
                                        marginRight: '5px'
                                    }
                                }, '*'),

                                h('span', {}, params.column.title)
                            ]);
                        },
                        render:(h, params)=>{console.log('行数据',params.index, params);

                            /**
                             * 2019 年 5 月 14 日 17:08:32 添加校验
                             */
                            let _formKey=params.column.key+'_'+params.row.id;

                            this.rulesTable[_formKey]=[];
                            // 2019 年 6 月 6 日 11:09:32 这步会导致,数据渲染两遍
                            this.$set(this.$data.formTable, _formKey,
                                params.row[params.column.key]===undefined || params.row[params.column.key]===null ? '' : params.row[params.column.key]);


                            this.rulesTable[_formKey].push(
                                {
                                    /**
                                     * 清掉 input 输入的空格,如果为空,不能通过
                                     */
                                    validator(rule, value, callback, source, options) {let errors = [];
                                        if (!Trim(value) ){
                                            errors.push(
                                                new Error("该项是必填项"));
                                        }
                                        callback(errors);
                                    }, trigger: 'blur'
                                },
                                {validator(rule, value, callback, source, options) {let errors = [];
                                        // 正则控制范围,比较大小,同时存在才为 true
                                        let _tmpValue= value && Number(value);
                                        // 可以出现一项:100 分,或者 n 项 几分~ 几十分
                                        let reg= /^([1-9]?[0-9]{1,2})?\0?(\.\d{1,2})?$/;

                                        if(!(reg.test(_tmpValue)&&0<=_tmpValue&&_tmpValue<=100))
                                        {errors.push( new Error("请输入 0 -100 之间的数字,小数点后最多允许保留 2 位小数") );
                                        }
                                        callback(errors);

                                    },type:'string', trigger: 'blur'
                                }
                            );
                            return h(FormItemInput, {
                                props:{
                                    formTable:this.formTable,
                                    formKey:_formKey,
                                },
                                on:{'on-form-blur':(value)=>{
                                        // 更新提交数据
                                        this.$refs.formTable.validateField(_formKey, (message)=>{
                                            //2019 年 5 月 16 日 10:12:08 校验通过以后,保留 2 位小数
                                            if(message.length==0)
                                            {this.formTable[_formKey]=Number(value).toFixed(2);
                                                console.log('formTable',this.formTable);
                                            }

                                        });
                                    }
                                }
                            });
                        }
                    },

                ],
                // +++++++ table end
            };
        },
        mounted() {},
        methods: {}}
</script>

form-item-input.vue

<template>
    <Form-item :prop="formKey" @on-form-blur="onFormBlur" :required="required" :label="label"
                 :setLengthNumber="setLengthNumber" :lastFormItem="lastFormItem">
        <Input v-model="formTable[formKey]" ></Input>
    </Form-item>
</template>
<script>
    export default {

        props:{
            required:{
                type:Boolean,
                default:false
            },
            label:{
                type:String,
                default:''
            },
            formTable:Object,
            formKey:String,
        },
        methods: {onFormBlur(value){this.$emit('on-form-blur', value);
            }

        }
    }
</script>

图示

问题

使用 this.$set(this.$data.formTable, _formKey, '') 处理数据可以实现数据的双向绑定。
但是会导致表格渲染两次。

解决

怎么解决呢????

注意

此处的 Form 表单和表格的样式等需要调整细节,不在本次的重点,可以忽略。

退出移动版