ant design 的vue批量操作

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的高度方法

    看图

    ant design 的vue批量操作(ant desing vue table 实现可伸缩列的完整例子)

    可拖拽区域为红色区域,为了达到这个效果,需要以下处理

    首先去除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 可伸缩列的资料请关注开心学习网其它相关文章!