ant desing vue table 實現可伸縮列的完整例子
完美解決ant-design-vue table 可伸縮列問題,實現在固定列,多級表頭情況下的伸縮列
這個東西本來以為手到擒來,因為在官網中已經給出瞭例子,但是果然還是不能太信任官方,官方給出來的隻能是最基礎的,然後我們正常的使用場景往往要復雜很多,比如固定列, 比如固定表頭,比如自帶checkbox列,比如多級表頭的情況。要想滿足這些情況往往需要自行開發。
1.首先蔣官方的例子copy下來,居然拖不動。
對照瞭一下官方,css居然都不一樣,於是增加瞭第一個改動
因為style內聯樣式自帶瞭 translate屬性,所以直接去掉right:0;隻留left -5.height設置100%就可以。
.resize-table-th { position: relative; .table-draggable-handle { height: 100% !important; bottom: 0; left: -5px !important; cursor: col-resize; touch-action: none; position: absolute; } }
2.這回可以看到每次拖拽後translate屬性實時在變化,但是單元格並沒有變寬移動。
於是又是檢查瞭元素,發現th的width在變化,但是colGroup的width屬性沒有變。於是開啟瞭尋找對應的colGroup的子元素col之旅,最後找到瞭,然後就是一頓操作在draging的時候同時修改瞭 colGroup的col的width屬性。這樣就可以跟著變化瞭。
3.接下來我發現在固定列和固定表頭的情況下拉伸會出現bug。
查看代碼發現當為固定列或者固定表頭的情況下實際上thead和tbody是在不同的 table上,這時候就需要找到所有的colGroup測col,改變width。這樣就處理瞭固定表頭的拉伸。但是固定列的情況還是需要另外設置css ,找到table-fixed-left重新設置寬度。
下面是一些代碼
根據當前的th,判斷th是父元素的第幾個孩子節點,對應到colGroup的第幾個col節點
const loopDom = ss => { if (ss.previousSibling !== null) { thDomIndex++; loopDom(ss.previousSibling); } };
重新設置固定列的寬度(隻處理瞭左浮動)
function resetFixedColumns(width) { const fixedHead = document.querySelector(".ant-table-fixed-left .ant-table-header"); const fixedBody = document.querySelector(".ant-table-fixed-left .ant-table-body-outer .ant-table-fixed"); if (fixedHead) { fixedHead.style.width = width + "px"; fixedBody.style.width = width + "px"; } }
解決多級表頭伸縮列問題
遞歸遍歷數組,獲取寬度
getDraggingMap(tbCols, draggingMap) { tbCols.forEach(col => { if (col.children) { this.getDraggingMap(col.children, draggingMap); } else { const key = col.dataIndex || col.key; //這兒要求表格數據中要有這兩個屬性 draggingMap[key] = col.width || 0; } }); },
遞歸遍歷數組,獲取當前列(這個遞歸真的很煩,不知道你們寫遞歸是什麼感受)
// 處理多級表頭 getRenderCoL(key, tbCols) { let result = ""; this._.forEach(tbCols, item => { if (item.children) { result = this.getRenderCoL(key, item.children); return !result; } else { const k = item.dataIndex || item.key; if (k === key) { result = item; return false; } } }); return result; }
遞歸遍歷數組, 獲取多級表頭操作列索引(同樣難以忍受的遞歸,開始少瞭最後一個renturn 一直跑不對,遞歸的陰影面積正無窮)
const loopDom = (cols, col) => { let tag = true; this._.forEach(cols, co => { if (co.dataIndex == col.dataIndex) { thDomIndex++; tag = false; return tag; } if (co.children) { tag = loopDom(co.children, col); return tag; } else { thDomIndex++; } }); return tag; };
下面是完整代碼
這是一個js文件,通過mixin的方式引入table主文件, table 添加
:components="drag(columnKeys)"
//mixins/tableDragResize.js import Vue from "vue"; import VueDraggableResizable from "vue-draggable-resizable"; Vue.component("vue-draggable-resizable", VueDraggableResizable); export default { data() { return { maxLevel: 1 }; }, methods: { drag(columns) { return { header: { cell: this.initDrag(columns) } }; }, /** * @param { 表格columns } tbCols */ initDrag(tbCols) { let draggingMap = {}; this.getDraggingMap(tbCols, draggingMap, 1); let draggingState = Vue.observable(draggingMap); return (h, props, children) => { let thDomIndex = 0; const { key, ...restProps } = props; let col = {}; // 處理多級表頭 col = this.getRenderCoL(key, tbCols); if (!col || !col.width) { //這兒要求表格數據中要有寬width屬性,若是沒有是不會執行下面的拖拽的 return <th {...restProps}>{children}</th>; } const onDrag = x => { col.width = Math.max(x, 1); draggingState[key] = col.width; thDomIndex = 0; loopDom(tbCols, col); if (!this.attrBute.isCheck) { thDomIndex--; } let colgroup = document.querySelectorAll("colgroup"); colgroup.forEach(Element => { let childCol = Element.children; if (childCol[thDomIndex]) childCol[thDomIndex].style.width = col.width + "px"; }); this.resetFixedColumns(col.width); }; const loopDom = (cols, col) => { let tag = true; this._.forEach(cols, co => { if (co.dataIndex == col.dataIndex) { thDomIndex++; tag = false; return tag; } if (co.children) { tag = loopDom(co.children, col); return tag; } else { thDomIndex++; } }); return tag; }; const onDragstop = () => {}; return ( <th {...restProps} width={draggingState[key]} class="resize-table-th" dataIndex={col.key}> {children} <vue-draggable-resizable key={col.dataIndex || col.key} class="table-draggable-handle" w={20} h={this.getResizableHandler(col)} x={draggingState[key]} z={100} axis="x" draggable={true} resizable={false} onDragging={onDrag} onDragstop={onDragstop} ></vue-draggable-resizable> </th> ); }; }, getResizableHandler(col) { // let baseH = thDom.getBoundingClientRect().height; let size = this.cellsize ? this.cellsize : this.attrBute.cellsize; let baseH = size == "middle" ? 47 : size == "small" ? 39 : 55; if (col.isEndNode) return baseH * col.nodeLevel; else if (col.leafNode && col.nodeLevel < this.maxLevel) { return baseH * this.maxLevel; } else return baseH; }, resetFixedColumns(width) { const fixedHead = document.querySelector(".ant-table-fixed-left .ant-table-header"); const fixedBody = document.querySelector(".ant-table-fixed-left .ant-table-body-outer .ant-table-fixed"); if (fixedHead) { fixedHead.style.width = width + "px"; fixedBody.style.width = width + "px"; } }, getDraggingMap(tbCols, draggingMap, nodeLevel) { tbCols.forEach((col, index) => { col.nodeLevel = nodeLevel; col.isEndNode = index == tbCols.length - 1; this.maxLevel = Math.max(this.maxLevel, nodeLevel); if (col.children) { col.leafNode = false; this.getDraggingMap(col.children, draggingMap, nodeLevel + 1); } else { col.leafNode = true; const key = col.dataIndex || col.key; //這兒要求表格數據中要有這兩個屬性 draggingMap[key] = col.width || 0; } }); }, getRenderCoL(key, tbCols) { let result = ""; this._.forEach(tbCols, item => { if (item.children) { result = this.getRenderCoL(key, item.children); return !result; } else { const k = item.dataIndex || item.key; if (k === key) { result = item; return false; } } }); return result; } } };
後記 完美解決多級表頭的伸縮列 修改原getDraggingMap方法,增加nodeLevel 層級, isEndNode是否是蓋層級下最後一個節點, 以及this.maxLevel 記錄最大層級
getDraggingMap(tbCols, draggingMap, nodeLevel) { tbCols.forEach((col, index) => { col.nodeLevel = nodeLevel; col.isEndNode = index == tbCols.length - 1; this.maxLevel = Math.max(this.maxLevel, nodeLevel); if (col.children) { col.leafNode = false; this.getDraggingMap(col.children, draggingMap, nodeLevel + 1); } else { col.leafNode = true; const key = col.dataIndex || col.key; //這兒要求表格數據中要有這兩個屬性 draggingMap[key] = col.width || 0; } }); },
增加處理 table-draggable-handle的高度方法
看圖
可拖拽區域為紅色區域,為瞭達到這個效果,需要以下處理
首先去除css 中height :100%;
然後在render時 設置組件高度如下
h={this.getResizableHandler(col)}
size 是表格尺寸
getResizableHandler(col) { // let baseH = thDom.getBoundingClientRect().height; let size = this.cellsize ? this.cellsize : this.attrBute.cellsize; let baseH = size == "middle" ? 47 : size == "small" ? 39 : 55; if (col.isEndNode) return baseH * col.nodeLevel; else if (col.leafNode && col.nodeLevel < this.maxLevel) { return baseH * this.maxLevel; } else return baseH; },
完結
以上就是ant desing vue table 實現可伸縮列的詳細內容,更多關於ant desing vue table 可伸縮列的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- el-table表頭根據內容自適應完美解決表頭錯位和固定列錯位
- react中useState使用:如何實現在當前表格直接更改數據
- javascript ES6中set集合、map集合使用方法詳解與源碼實例
- JS中數組常用的循環遍歷你會幾種
- 基於ElementUI中Table嵌套實現多選的示例代碼