• 吐槽!iview的table组件


    为什么要吐槽iview的table组件呢?

    首先iview的table的使用体验十分的不友好,每次修改数据都会重刷整个表格,性能极差,因为重刷表格会导致自动失焦等问题!

    vue不是有diff算法吗?重刷表格数据没有发生变化部分是不会重新渲染的,性能为什么会差呢?

    是的,diff算法是可以优化vnode的渲染问题,但是前提是key,tag等属性没有发生变化的情况,可是万恶的iview table既然私自修改了key的值,导致diff的优化失效。

    如何解决这个问题?

    table组件data属性接收的数据源与实际操作的数据分离,例如:以下例子的tempData与data。

    <Table border :columns="columns"  :data="tempData"></Table>
    export default {
        data:{
            tempData:[],
            columns:[
                    {
                        title:'商品价格(元)',
                        120,
                        align: 'center',
                        render:(h,params)=>{
                            let data = this.data[params.index];  // 实际更改的是this.data的数据,因为tempData没有改变,所以table不会重新渲染
                            return <i-input maxlength={8} number value={data.value} on-on-blur={(e)=>{data.value=e.target.value} />;
                        }
                    },
            ],
            data:[]
        },
        watch:{
            data(val){
                this.tempData = util.deepCopy(val);
            },
       }
    }

    table组件的内容主题table-body组件,table-body的data属性接收的是rebildData

                <div :class="[prefixCls + '-body']" :style="bodyStyle" ref="body" @scroll="handleBodyScroll"
                    v-show="!((!!localeNoDataText && (!data || data.length === 0)) || (!!localeNoFilteredDataText && (!rebuildData || rebuildData.length === 0)))">
                    <table-body
                        ref="tbody"
                        :prefix-cls="prefixCls"
                        :styleObject="tableStyle"
                        :columns="cloneColumns"
                        :data="rebuildData"
                        :columns-width="columnsWidth"
                        :obj-data="objData"></table-body>
                </div>

    table组件内部实现深度监听了data属性,当data的任意属性发生变化就会重新生成rebuildData。(深度拷贝一份原有的data)为什么要拷贝一份呢?

    解:为了防止table组件内部直接通过params.row直接修改数据源,直接修改数据源容易导致bug难追溯,数据容易错乱等情况,增加维护成本!

           watch: {
                data: {
                    handler () {
                        const oldDataLen = this.rebuildData.length;
                        this.objData = this.makeObjData();
                        this.rebuildData = this.makeDataWithSortAndFilter();
                        this.handleResize();
                        if (!oldDataLen) {
                            this.fixedHeader();
                        }
                        // here will trigger before clickCurrentRow, so use async
                        setTimeout(() => {
                            this.cloneData = deepCopy(this.data);
                        }, 0);
                    },
                    deep: true
                },
      .....  
    }

    生成新的data数据,并重置每一项数据的_rowKey属性(该属性被table-tr组件当作key来使用),_rowKey是全局递增的,每一次table重新render,_rowKey都会不断递增,导致diff算法失效(导致表格重新渲染的元凶)

                makeDataWithSortAndFilter () {
                    let data = this.makeDataWithSort();
                    this.cloneColumns.forEach(col => data = this.filterData(data, col));
                    return data;
                },
                makeDataWithSort () {
                    let data = this.makeData();
                    let sortType = 'normal';
                    let sortIndex = -1;
                    let isCustom = false;
    
                    for (let i = 0; i < this.cloneColumns.length; i++) {
                        if (this.cloneColumns[i]._sortType !== 'normal') {
                            sortType = this.cloneColumns[i]._sortType;
                            sortIndex = i;
                            isCustom = this.cloneColumns[i].sortable === 'custom';
                            break;
                        }
                    }
                    if (sortType !== 'normal' && !isCustom) data =  this.sortData(data, sortType, sortIndex);
                    return data;
                },
    // 生成新的data makeData () { let data
    = deepCopy(this.data); data.forEach((row, index) => { row._index = index; row._rowKey = rowKey++; //rowKey 全局的一个变量 初始值 rowKey=0 }); return data; },
  • 相关阅读:
    ADO.NET的记忆碎片(四)
    ADO.NET的记忆碎片(八)
    卡特兰数 应用
    hdu 1249 三角形
    hdu 1143
    nyist 93 汉诺塔(三)
    hdu 1123 Train Problem II
    hdu 1133 Buy the Ticket
    hdu 1022 Train Problem I
    nyist 610 定长覆盖
  • 原文地址:https://www.cnblogs.com/dudeyouth/p/10730618.html
Copyright © 2020-2023  润新知