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 可伸缩列的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue 公共列表选择组件,引用Vant-UI的样式方式

    此组件用于公共选择组件.引用Vant UI 作为样式 特性: 1.支持动态.静态数据源. 2.支持分页加载. 3.支持模糊搜索. 4.支持单选.多选. 组件源码: <template> <div class="gn-PubSelect"> <van-action-sheet v-model="inShow"> <div class="gn-PubSelect-main" :style="{'he

  • vue+vant实现商品列表批量倒计时功能

    最近因为一个项目需要用到商品批量倒计时,当时使用vant封装好的组件CountDown编写 起初不知道"timeData"这个对象只需要传time的时间戳就可以自动生成,走了一大波弯路,现在想想也是醉了 最开始写这个倒计时的时候没有考虑到使用当前服务器时间问题,只获取了本地时间 new Date().getTime(),然后发现这个不行,只要用户修改下手机本地时间,这个倒计时就不行了,有安全隐患,在网上也搜了一些相关知识,但都不尽人意,故想写这一篇文章避免大家再走我之前的弯路! 废话不

  • Ant Design Vue table中列超长显示...并加提示语的实例

    我就废话不多说了,大家还是直接看代码吧~ <template> <a-row class="a-left"> <a-row> <p class="a-title">今日考勤状况</p> <a-row type="flex" justify="space-around"> <a-col :span="4" class="b

  • ant desing vue table 实现可伸缩列的完整例子

    完美解决ant-design-vue table 可伸缩列问题,实现在固定列,多级表头情况下的伸缩列 这个东西本来以为手到擒来,因为在官网中已经给出了例子,但是果然还是不能太信任官方,官方给出来的只能是最基础的,然后我们正常的使用场景往往要复杂很多,比如固定列, 比如固定表头,比如自带checkbox列,比如多级表头的情况.要想满足这些情况往往需要自行开发. 1.首先蒋官方的例子copy下来,居然拖不动. 对照了一下官方,css居然都不一样,于是增加了第一个改动 因为style内联样式自带了 t

  • Ant design vue table 单击行选中 勾选checkbox教程

    最近了解Ant design 设计table 单击行选中checkedbox功能,相比于element的 @row-click 再触发toggleRowSelection,ant design的api就没那么清晰了,言归正传 期望:Ant design table 单击行选中 勾选checkedbox 实现: 单选: onClickRow(record) { return { on: { click: () => { let keys = []; keys.push(record.id); th

  • Ant Design Vue中的table与pagination的联合使用方式

    目录 Ant Design Vue中table与pagination联合使用 ant.design.vue中table的使用说明 table的创建 table之columns table之dataSource table之loading table之scroll table之rowKey table之rowSelection table之customRow table之change Ant Design Vue中table与pagination联合使用 表格table使用链接:ant desig

  • ant design vue的table取消自带分页问题

    目录 ant design vue的table取消自带分页 题外话: ant design vue table分页 ant design vue table分页设置 ant design vue的table取消自带分页 在我们使用ant design vue的table组件的时候会发现: 组件使用如示: <a-table :columns="columns" :data-source="data" bordered></a-table> 显然

  • ant design vue 表格table 默认勾选几项的操作

    为什么我同样的功能要用react .vue 都写一遍 ? 啊我真是不是闲的蛋疼啊(- o -)~zZ 在 ant design vue 中,表格的第一列是联动的选择框 截一张官方文档图,图示最后一排就是禁用状态 点击 checkbox 会触发onChange , 从而得到selectedRowKeys,selectedRowKeys就是选中的 key 数组. onChange: (selectedRowKeys, selectedRows) => { console.log(`selectedR

  • VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)

    一.问题 用elementUi横着增加一行数据没毛病,可以操作 添加一列,这新增的这一列, 第一次去赋值的时候值是改了, 但没生效 点击下一行时 值就变过来 二.原因 横向添加 是复制上面的某一条数据来的,因为data里面有这些属性的定义,所以横向添加没问题 而纵向添加的数据,因为没有事先在 el-select v-modle="" 里面定义好字段,定义好的option是通过v-for出来的(option是写死的就不会有这个问题),就会出现选择后,select元素上无法展示,但是其实数

  • vue用ant design中table表格,点击某行时触发的事件操作

    使用customRow 设置行属性,写对应事件 :customRow="rowClick" 然后在data里面写 rowClick: record => ({ // 事件 on: { click: () => { // 点击改行时要做的事情 // ...... console.log(record, 'record') } } }) 在官方文档中也写的很清楚 补充知识:Ant-Design-Vue table 合并单元格,并且添加点击事件 点击行,有一个customRow.

  • vue element-ui中table合计指定列求和实例

    注意点: 1. <el-table> 中 加:summary-method="getSummaries" 2. <el-table-column> 中要加 prop // 房间号的合计去掉 getSummaries (param) { const { columns, data } = param const sums = [] columns.forEach((column, index) => { if (index === 0) { sums[ind

  • vue.js Table 组件自定义列宽实现核心方法

    目录 前言 colgroup 和 col 核心实现 一些常量/变量定义 初始化表头列表 initColumns 处理含有固定宽度和最小宽的列 获取各列宽度,并组成一个数组 getWidthList 计算需要自适应的列宽度 getAdaptWidth 监听屏幕变化和属性更新 前言 如果你使用过类似于 ElementUI 的组件库,一定对如下的 API 属性不眼生,例如: <!-- Element UI --> <el-table-column prop="date" l

随机推荐