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

> 文 / 景朝霞

> 来源公号 / 朝霞的光影笔记

> ID / zhaoxiajingjing

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

0 / 更新Table

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

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

1 / Table的拖拽适配列

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

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

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

(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](https://segmentfault.com/img/remote/1460000022293350 "公号ID:zhaoxiajiingjing")

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

【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给出的例子,只需要把合并的规则传入到组件内即可

△图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:我动了源码这很不好,望大佬不吝赐教更好的方案

<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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值