文 / 景朝霞
來(lái)源公號(hào) / 朝霞的光影筆記
ID / zhaoxiajingjing
????點(diǎn)個(gè)贊,讓我知道你來(lái)過(guò)~????
0 / 更新Table
"iview": "2.13.0",
對(duì)比最新版本的iview:4.1.3
中的Table功能谈宛,獲取最新功能:拖拽次哈、合并行等。
【PS:由于一些原因不能統(tǒng)一升級(jí)整個(gè)iview吆录,我動(dòng)了源碼這很不好窑滞,望大佬們不吝賜教更好的方案~】
1 / Table的拖拽適配列
在table.vue
文件中handleResize
方法里實(shí)現(xiàn)了:
不設(shè)置列的屬性width
,而是設(shè)置屬性maxWidth
和minWidth
用來(lái)適配在拖拽時(shí)表格產(chǎn)生的留白的適配恢筝,會(huì)把留白的寬度平均分配給適配列哀卫。
其中,最后呈現(xiàn)的寬度不會(huì)比最小寬還小撬槽,不會(huì)比最大寬度還大此改。
(1)拖拽設(shè)置邊界值
為了使拖拽后的表格不會(huì)無(wú)限制的寬,也不會(huì)特別窄侄柔,設(shè)置邊界值:
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)可拖拽范圍加寬
把鼠標(biāo)可拖拽的范圍放寬:
if (rect.width > 12 && rect.right - event.pageX < 8)
// 把判斷條件的8改為16
table.less
.@{table-prefix-cls} {
&-header{
&-resizable{
width: 20px; // 把原來(lái)的10px更新為20px
}
}
}
2 / Table的自定義固定列
△圖12.1:用戶(hù)可以自己配置固定列
△圖12.2:固定后的結(jié)果
【PS:實(shí)現(xiàn)此功能共啃,請(qǐng)?jiān)徫倚薷牧嗽创a】
在列上添加屬性freezable:true
表示允許用戶(hù)自己設(shè)置固定列,其代碼里面操作的依舊是列的屬性fixed
實(shí)現(xiàn)效果暂题。
(1)新增泡泡文件freeze-poptip.vue
<template>
<!-- 2020年3月10日10:01:50 可以?xún)鼋Y(jié) -->
<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)在表頭添加凍結(jié)提示泡泡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'" >左側(cè)凍結(jié)</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'">右側(cè)凍結(jié)</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>
添加點(diǎn)擊方法
// 2020年3月10日10:08:28 凍結(jié)
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)應(yīng)用
應(yīng)用的代碼在文末
3 / Table的合并行
(1)閱讀iview的源碼
根據(jù)iview給出的例子移剪,只需要把合并的規(guī)則傳入到組件內(nèi)即可
△圖12.3:iview的Table合并行的例子
table-body.vue
在這里可以學(xué)習(xí)一下,如何判斷一個(gè)方法的返回值是數(shù)組還是對(duì)象
getSpan (row, column, rowIndex, columnIndex) {
// 拿到傳過(guò)來(lái)的方法 spanMethod
const fn = this.$parent.spanMethod;
// 是function類(lèi)型的才可以
if (typeof fn === 'function') {
// 調(diào)用該方法薪者,并把返回值結(jié)果賦值給變量result
const result = fn({
row,
column,
rowIndex,
columnIndex
});
// 設(shè)置初始值
let rowspan = 1;
let colspan = 1;
if (Array.isArray(result)) {
// 返回結(jié)果值是數(shù)組
rowspan = result[0];
colspan = result[1];
} else if (typeof result === 'object') {
// 返回結(jié)果值是對(duì)象
rowspan = result.rowspan;
colspan = result.colspan;
}
return {
rowspan,
colspan
};
} else { // 否則:{}
return {};
}
},
(1)判斷是否為函數(shù)typeof fn === 'function'
(2)判斷是否為數(shù)組Array.isArray(result)
(3)判斷是否為對(duì)象typeof result === 'object'
【僅限于此處約定的返回值是一個(gè)對(duì)象或者一個(gè)數(shù)組】
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
}
}
可以看到它的表格數(shù)據(jù)data5
是一條一條寫(xiě)的纵苛。
對(duì)于我們想要的數(shù)據(jù)格式如下,那就需要處理一下了言津,具體方法見(jiàn)文末
[
{
"teacher":"教師1",
"course":"語(yǔ)文",
"studentList":[
{
"student":"學(xué)生1"
},
{
"student":"學(xué)生2"
}
]
}
]
(2)鼠標(biāo)移入的樣式
△圖12.4:鼠標(biāo)移入的樣式
思路:在設(shè)置合并行的時(shí)候攻人,給一個(gè)統(tǒng)一的標(biāo)識(shí)符,在鼠標(biāo)移入后悬槽,把帶有該標(biāo)識(shí)符的都加上移入的樣式
【PS:大佬們打臉輕一些贝椿,請(qǐng)不吝賜教更好的方案】
△圖12.5:給tr加上行標(biāo)識(shí)
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 / 應(yīng)用
PS:自定義凍結(jié)是修改的源碼,如需要該功能陷谱,請(qǐng)自行貼上面介紹的代碼
PS:我動(dòng)了源碼這很不好,望大佬不吝賜教更好的方案
【你可能感興趣】
<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:'教師編號(hào)',
key:'teacherCode',
resizable:true,
freezable:true,
width:120
},
{
title:'課程',
key:'course',
resizable:true,
freezable:true,
width:120
},
{
title:'學(xué)生',
key:'student',
rowRelation:'many',
resizable:true,
freezable:true,
width:100
},
{
title:'學(xué)號(hào)',
key:'studentCode',
rowRelation:'many',
resizable:true,
width:120
},
{
title:'成績(jī)',
key:'score',
rowRelation:'many',
resizable:true,
freezable:true,
width:100
},
{
title:'批語(yǔ)',
key:'explain',
rowRelation:'many',
freezable:true,
minWidth:100
}
],
data3:[],
tableDataArr3:[
{
"id":1,
"teacher":"Name 1",
"teacherCode":"Teacher-1",
"course":"語(yǔ)文",
"studentList":[
{
"studentCode":"2020001",
"student":"學(xué)生1",
"score":"A",
"explain":""
},
{
"studentCode":"2020002",
"student":"學(xué)生2",
"score":"B",
"explain":""
},
{
"studentCode":"2020003",
"student":"學(xué)生3",
"score":"B",
"explain":""
},
{
"studentCode":"2020004",
"student":"學(xué)生4",
"score":"A",
"explain":""
}
]
},
{
"id":2,
"teacher":"Name 2",
"teacherCode":"Teacher-2",
"course":"物理",
"studentList":[
{
"studentCode":"2020001",
"student":"學(xué)生1",
"score":"B",
"explain":""
},
{
"studentCode":"2020002",
"student":"學(xué)生2",
"score":"B",
"explain":""
},
{
"studentCode":"2020003",
"student":"學(xué)生3",
"score":"B",
"explain":""
}
]
},
{
"id":3,
"teacher":"Name 3",
"teacherCode":"Teacher-3",
"course":"歷史",
"studentList":[
{
"studentCode":"2020003",
"student":"學(xué)生3",
"score":"A",
"explain":""
},
{
"studentCode":"2020004",
"student":"學(xué)生4",
"score":"A",
"explain":""
}
]
},
{
"id":4,
"teacher":"Name 4",
"teacherCode":"Teacher-4",
"course":"美術(shù)",
"studentList":[
{
"studentCode":"2020004",
"student":"學(xué)生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 需要處理的數(shù)據(jù)數(shù)組
* @param rowspanList 合并行的數(shù)組
* @param rowspanHoverFlag 作為鼠標(biāo)滑入的行的標(biāo)記
* @returns {*} [Array] 將處理好的數(shù)據(jù)返回去
*/
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>