美文网首页
案例 | iview中Table:拖拽适配列、自定义固定列、合并

案例 | iview中Table:拖拽适配列、自定义固定列、合并

作者: 鲸鲸景鲸叻 | 来源:发表于2020-04-07 21:30 被阅读0次

    文 / 景朝霞
    来源公号 / 朝霞的光影笔记
    ID / zhaoxiajingjing

    ❥❥❥❥点个赞,让我知道你来过~❥❥❥❥


    0 / 更新Table

    "iview": "2.13.0",对比最新版本的iview:4.1.3中的Table功能,获取最新功能:拖拽、合并行等。

    【PS:由于一些原因不能统一升级整个iview,我动了源码这很不好,望大佬们不吝赐教更好的方案~】

    1 / Table的拖拽适配列

    table.vue文件中handleResize方法里实现了:

    不设置列的属性width,而是设置属性maxWidthminWidth用来适配在拖拽时表格产生的留白的适配,会把留白的宽度平均分配给适配列。

    其中,最后呈现的宽度不会比最小宽还小,不会比最大宽度还大。

    (1)拖拽设置边界值

    为了使拖拽后的表格不会无限制的宽,也不会特别窄,设置边界值:

    table.vue

    minColumnWidth:{
        type:Number,
        default:50
    },
    maxColumnWidth:{
        type:Number,
        default:560
    }
    

    table-head.vue

    const columnWidth = _width < this.minColumnWidth ? this.minColumnWidth : (_width > this.maxColumnWidth ? this.maxColumnWidth : _width);
    
    (2)可拖拽范围加宽

    把鼠标可拖拽的范围放宽:

    if (rect.width > 12 && rect.right - event.pageX < 8) 
    // 把判断条件的8改为16
    

    table.less

    .@{table-prefix-cls} {
        &-header{
            &-resizable{
                width: 20px; // 把原来的10px更新为20px
            }
        }
    }
    

    2 / Table的自定义固定列

    公号ID:zhaoxiajiingjing

    △图12.1:用户可以自己配置固定列

    公号:朝霞的光影笔记

    △图12.2:固定后的结果

    【PS:实现此功能,请原谅我修改了源码】

    在列上添加属性freezable:true表示允许用户自己设置固定列,其代码里面操作的依旧是列的属性fixed实现效果。

    (1)新增泡泡文件freeze-poptip.vue
    <template>
        <!-- 2020年3月10日10:01:50 可以冻结 -->
        <Poptip
                v-model="showFlag"
                popper-class="ivu-table-popper "
                trigger="hover"
                placement="top" :transfer="true">
            <span :class="[prefixCls + '-freeze']">
                <Icon type="loudou" ></Icon>
            </span>
            <div slot="content" :class="[prefixCls + '-freeze-list']">
                <slot name="freezeContent"></slot>
            </div>
        </Poptip>
    </template>
    <script>
        import Poptip from '../poptip/poptip.vue';
    
        export default {
            components: { Poptip },
            props:{
                prefixCls: String,
                show:{
                    type:Boolean
                },
                hide:{
                    type:Boolean
                }
            },
            watch:{
                hide(newFlag, oldFlag){
                    if(newFlag === false) {
                        this.showFlag = false;
                    }
                }
            },
            data() {
                return {
                    showFlag:this.show
                };
            }
        }
    </script>
    
    (2)在表头添加冻结提示泡泡table-head.vue

    import FreezePoptip from './freeze-poptip.vue';

    <FreezePoptip v-if="column.freezable"
        :show="getColumn(rowIndex, index)._freezeVisible"
                  :prefixCls="prefixCls"
                  :hide="getColumn(rowIndex, index)._freezeVisiblePoptip"
    >
        <template slot="freezeContent">
            <ul :class="[prefixCls + '-freeze-list-single']">
                <li :class="[prefixCls + '-filter-select-item']"
                    @click="handleFreezable(getColumn(rowIndex, index)._index, 'left')">
                    <Button type="text" :class="[prefixCls + '-freeze-btn']"
                              :disabled="column.fixed === 'left'" >左侧冻结</Button>
                </li>
                <li :class="[prefixCls + '-filter-select-item']"
                    @click="handleFreezable(getColumn(rowIndex, index)._index, 'right')">
                    <Button type="text" :class="[prefixCls + '-freeze-btn']"
                              :disabled="column.fixed === 'right'">右侧冻结</Button>
                </li>
                <li :class="[prefixCls + '-filter-select-item']"
                    @click="handleFreezable(getColumn(rowIndex, index)._index, '')">
                    <Button type="text" :class="[prefixCls + '-freeze-btn']"
                              :disabled="(typeof column.fixed === 'string' && column.fixed.length === 0) || typeof column.fixed === 'undefined'" >还原</Button>
                </li>
            </ul>
        </template>
    </FreezePoptip>
    

    添加点击方法

    // 2020年3月10日10:08:28 冻结
    handleFreezable(index, type){
        const column = this.columns.find(item => item._index === index);
        const _index = column._index;
        this.$parent.handleFreezable(_index, type);
    },
    
    (3)修改table.vue
    handleFreezable(_index, type){
        const index = this.GetOriginalIndex(_index);
        const key = this.cloneColumns[index].key;
        this.cloneColumns[index]._freezeVisiblePoptip = false;
        this.$emit('on-freeze-change', {
            column:JSON.parse(JSON.stringify(this.allColumns[this.cloneColumns[index]._index])),
            key,
            fixed:type
        });
    
    },
    
     makeColumns (cols) {
         //....CODE
         let hasFreezable = columns.some(col => col.freezable===true);
         let hasResizable = columns.some(col => col.resizable===true);
         columns.forEach((column, index) => {
             //...CODE
             (hasFreezable || hasResizable ) && (column.width = parseInt(column.width));
             //...CODE
         });
         //....CODE
     }
    
    (4)应用

    应用的代码在文末

    3 / Table的合并行

    (1)阅读iview的源码

    根据iview给出的例子,只需要把合并的规则传入到组件内即可

    https://www.iviewui.com/components/table#H/LHB

    公号ID:zhaoxiajingjing

    △图12.3:iview的Table合并行的例子

    table-body.vue在这里可以学习一下,如何判断一个方法的返回值是数组还是对象

    getSpan (row, column, rowIndex, columnIndex) {
        // 拿到传过来的方法 spanMethod
        const fn = this.$parent.spanMethod;
        // 是function类型的才可以
        if (typeof fn === 'function') {
            // 调用该方法,并把返回值结果赋值给变量result
            const result = fn({
                row,
                column,
                rowIndex,
                columnIndex
            });
            // 设置初始值
            let rowspan = 1;
            let colspan = 1;
            if (Array.isArray(result)) { 
                // 返回结果值是数组
                rowspan = result[0];
                colspan = result[1];
            } else if (typeof result === 'object') {  
                // 返回结果值是对象
                rowspan = result.rowspan;
                colspan = result.colspan;
            }
            return {
                rowspan,
                colspan
            };
        } else { // 否则:{}
            return {};
        }
    },
    

    (1)判断是否为函数typeof fn === 'function'

    (2)判断是否为数组Array.isArray(result)

    (3)判断是否为对象typeof result === 'object'【仅限于此处约定的返回值是一个对象或者一个数组】

    let fn = function (){
        return [];
    };
    if (typeof fn === 'function'){ // (1)
        const result = fn();
        if (Array.isArray(result)) { // (2)
            // ...something
        } else if (typeof result === 'object') { //(3)
            // ...something
        }
    }
    

    可以看到它的表格数据data5是一条一条写的。

    对于我们想要的数据格式如下,那就需要处理一下了,具体方法见文末

    [
        {
            "teacher":"教师1",
            "course":"语文",
            "studentList":[
                {
                    "student":"学生1"
                },
                {
                    "student":"学生2"
                }
            ]
        }
    ]
    
    (2)鼠标移入的样式
    公号:朝霞的光影笔记

    △图12.4:鼠标移入的样式

    思路:在设置合并行的时候,给一个统一的标识符,在鼠标移入后,把带有该标识符的都加上移入的样式

    【PS:大佬们打脸轻一些,请不吝赐教更好的方案】

    公号:朝霞的光影笔记

    △图12.5:给tr加上行标识

    rowClasses (_index) {
        // ...CODE
        let {rowspanHoverFlag} = objData;
        
        if(rowspanHoverFlag && objData){
            for (let rowIndex in this.objData) {
                let row = this.objData[rowIndex];
                if(row.rowspanHoverFlag === rowspanHoverFlag && this.$parent.$el) {
                    let el = this.$parent.$el.querySelector(`.myhoverindex-${rowIndex}`);
        
                    let _class = objData._isHover ?
                        ( `myhoverindex-${rowIndex} ${this.prefixCls}-row ${this.rowClsName(rowIndex)} ${this.prefixCls}-row-highlight ${this.prefixCls}-row-hover`)
                        : (`myhoverindex-${rowIndex} ${this.prefixCls}-row ${this.rowClsName(rowIndex)}`);
        
                    (el!==null && el.setAttribute) && el.setAttribute('class',_class);
                }
            }
        }
        // ...CODE
    }
    

    4 / 应用

    PS:自定义冻结是修改的源码,如需要该功能,请自行贴上面介绍的代码

    PS:我动了源码这很不好,望大佬不吝赐教更好的方案

    公号ID:zhaoxiajingjing

    【你可能感兴趣】

    1. 题目 | let和var的区别(一、二)
    2. 图解 | let和var的区别(一、二)
    3. 题目 | 带VAR和不带VAR的区别
    4. 图解 | 带VAR和不带VAR的区别
    5. 总结 | LET和VAR区别(三、四)
    6. 图解 | 作用域和作用域链
    7. 练习题 | 作用域和作用域链
    8. 图解 | 理解闭包
    9. 案例 | 闭包作用:保护和保存
    <template>
        <Table
                    border
                    ref="selection"
                    :columns="columns3"
                    :data="data3"
                    :span-method="handleSpan"
                    @on-freeze-change="onFreezeChange"
    
            ></Table>
    </template>
    <script>
    
        export default {
    
            data() {
                return {
                    columns3:[
                        {
                            title:'教师',
                            key:'teacher',
                            resizable:true,
                            freezable:true,
                            width:100
                        },
                        {
                            title:'教师编号',
                            key:'teacherCode',
                            resizable:true,
                            freezable:true,
                            width:120
                        },
                        {
                            title:'课程',
                            key:'course',
                            resizable:true,
                            freezable:true,
                            width:120
                        },
                        {
                            title:'学生',
                            key:'student',
                            rowRelation:'many',
                            resizable:true,
                            freezable:true,
                            width:100
                        },
                        {
                            title:'学号',
                            key:'studentCode',
                            rowRelation:'many',
                            resizable:true,
                            width:120
                        },
                        {
                            title:'成绩',
                            key:'score',
                            rowRelation:'many',
                            resizable:true,
                            freezable:true,
                            width:100
                        },
                        {
                            title:'批语',
                            key:'explain',
                            rowRelation:'many',
                            freezable:true,
                            minWidth:100
                        }
                    ],
                    data3:[],
                    tableDataArr3:[
                        {
                            "id":1,
                            "teacher":"Name 1",
                            "teacherCode":"Teacher-1",
                            "course":"语文",
                            "studentList":[
                                {
                                    "studentCode":"2020001",
                                    "student":"学生1",
                                    "score":"A",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020002",
                                    "student":"学生2",
                                    "score":"B",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020003",
                                    "student":"学生3",
                                    "score":"B",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020004",
                                    "student":"学生4",
                                    "score":"A",
                                    "explain":""
                                }
                            ]
                        },
                        {
                            "id":2,
                            "teacher":"Name 2",
                            "teacherCode":"Teacher-2",
                            "course":"物理",
                            "studentList":[
                                {
                                    "studentCode":"2020001",
                                    "student":"学生1",
                                    "score":"B",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020002",
                                    "student":"学生2",
                                    "score":"B",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020003",
                                    "student":"学生3",
                                    "score":"B",
                                    "explain":""
                                }
                            ]
                        },
                        {
                            "id":3,
                            "teacher":"Name 3",
                            "teacherCode":"Teacher-3",
                            "course":"历史",
                            "studentList":[
                                {
                                    "studentCode":"2020003",
                                    "student":"学生3",
                                    "score":"A",
                                    "explain":""
                                },
                                {
                                    "studentCode":"2020004",
                                    "student":"学生4",
                                    "score":"A",
                                    "explain":""
                                }
                            ]
                        },
                        {
                            "id":4,
                            "teacher":"Name 4",
                            "teacherCode":"Teacher-4",
                            "course":"美术",
                            "studentList":[
                                {
                                    "studentCode":"2020004",
                                    "student":"学生4",
                                    "score":"A",
                                    "explain":""
                                }
                            ]
                        }
                    ],
                };
            },
            mounted() {
                setTimeout(() => {
                    this.data3 = this.data2TdRowspan({tableData:this.tableDataArr3, rowspanList:'studentList'});
                }, 300);
            },
            methods: {
                onFreezeChange({column = {}, key = '', fixed = ''} = {}) {
                    this.columns3 = this.columns3.map((col, index) =>{
                        if (col.key === key) {
                            col['fixed'] = fixed;
                        }
                        return col;
                    });
                },
                /**
                 * 2020年4月2日09:53:02 by jing_zhaoxia@sina.com
                 * @param arr 需要处理的数据数组
                 * @param rowspanList 合并行的数组
                 * @param rowspanHoverFlag 作为鼠标滑入的行的标记
                 * @returns {*} [Array] 将处理好的数据返回去
                 */
                data2TdRowspan(params){
                    let json = {};
    
                    if (Array.isArray(params)) {
                        json.tableData = params;
                    } else if(Object.prototype.toString.call(params) === '[object Object]'){
                        json = params;
                    }
    
                    let {tableData:arr = [], rowspanList = 'studentList', rowspanHoverFlag='id'} = json;
    
                    return arr.map((row, index) =>{
                        let rowspanArr = row[rowspanList];
                        let rowspan = rowspanArr.length;
    
                        return rowspanArr.map((sRow, sIndex) => {
                            sIndex === 0 ? row.rowspan = rowspan : (row.rowspan = 0, row._rowspan = rowspan);
    
                            sRow.rowspanHoverFlag = row[rowspanHoverFlag];
    
                            delete row[rowspanList];
    
                            return { ...sRow, ...row};
                        });
                    }).flat(Infinity);
                },
                handleSpan({row:{rowspan}, column:{rowRelation='', isExtended=false}}) {
                    return rowRelation !== 'many' ? {rowspan} : {};
                }
            }
        };
    </script>
    

    相关文章

      网友评论

          本文标题:案例 | iview中Table:拖拽适配列、自定义固定列、合并

          本文链接:https://www.haomeiwen.com/subject/nsiophtx.html