当前位置: 首页 > 工具软件 > vue-ellipsis > 使用案例 >

ant-design-vue的a-table组件中集成vue-draggable-resizable实现可伸缩列遇到的各种坑

龙永思
2023-12-01

**
近期想换一套ui框架,就选择了an design vue,但是发现table组件本身没有像element ui一样集成了列可以伸缩,看到官网提供了一个插件vue-draggable-resizable,我按照官网的例子copy了一下,遇到各种问题
1、我的colums数据没有写width
2、我有的列如操作列没有设置dataIndex 、key
3、我表格使用了复选框后一直报错Cannot read property ‘width’ of undefined
**

1、vue-draggable-resizable常用属性

:w 默认宽度
:h 默认高度
:x=“50” 默认水平坐标 注意相对元素是谁
:y=“50” 默认垂直最表 注意相对元素是谁
:min-width=“50” 最小宽度
:min-height=“50” 最小高度
:parent=“true” 限制不能拖出父元素
parent=".p-event" 限制不能拖出class为p-event的元素
:grid 水平和垂直移动 每次分别能够走多少像素
class-name 自定义组件class

2、vue-draggable-resizable常用事件

@dragging=“onDrag” 每当拖动组件时调用。
@resizing=“onResize” 每当组件调整大小时调用。
@dragstop=“onDragstop” 每当组件停止拖动时调用。
@resizestop=“onResizstop” 每当组件停止调整大小时调用
@deactivated=“onDeactivated” 每当用户单击组件外的任何位置时调用
@activated=“onActivated” 单击组件时调用,以显示句柄。备注:句柄就是点击组件后上下左右的可以拉伸的方块点

3、有了上面的基础知识和ant design vue官网的demo,我写了一个单独的js,然后混入到所有的表格组件中,如下是我的js代码

//mixins/tableDragResize.js
import Vue from 'vue'
import VueDraggableResizable from 'vue-draggable-resizable'
Vue.component('vue-draggable-resizable', VueDraggableResizable)
/**
 * @param { 表格columns } tbCols
 */
function initDrag(tbCols) {
  const draggingMap = {}
  tbCols.forEach((col) => {
    const key = col.dataIndex || col.key//这儿要求表格数据中要有这两个属性
    draggingMap[key] = col.width || 0
  })
  const draggingState = Vue.observable(draggingMap)
  return (h, props, children) => {
    let thDom = null
    const { key, ...restProps } = props
    let col
    if (key === 'selection-column') {
      //表格加了复选框,不加这个判断col会是undefided
      col = {}
    } else {
      col = tbCols.find((item) => {
        const k = item.dataIndex || item.key
        return k === key
      })
    }
    if (!col.width) {//这儿要求表格数据中要有宽width属性,若是没有是不会执行下面的拖拽的
      return <th {...restProps}>{children}</th>
    }

    const onDrag = (x) => {
      draggingState[key] = 0
      col.width = Math.max(x, 1)
    }
    const onDragstop = () => {
      draggingState[key] = thDom.getBoundingClientRect().width
    }

    return (
      <th
        {...restProps}
        v-ant-ref={(r) => {
          thDom = r
        }}
        width={draggingState[key]}
        class="resize-table-th"
      >
        {children}
        <vue-draggable-resizable
          key={col.dataIndex || col.key}
          class="table-draggable-handle"
          w={10}
          x={col.width || draggingState[key]}
          z={1}
          axis="x"
          draggable={true}
          resizable={false}
          onDragging={onDrag}
          onDragstop={onDragstop}
        ></vue-draggable-resizable>
      </th>
    )
  }
}
export default {
  methods: {
    /**
     * https://github.com/mauricius/vue-draggable-resizable
     * 表格列可拖拽
     * 表格上使用::components="drag(columns)"
     * tips:columns中需包含dataIndex或者key和width(Number)
     */
    drag(columns) {
      return {
        header: {
          cell: initDrag(columns),
        },
      }
    },
  },
}

使用的代码如下:

//user.vue
<template>
<a-table
       bordered
      :components="drag(tableColumns)"
      :columns="tableColumns"
      :data-source="userList"
      :row-selection="rowSelection"
      rowKey="userId"
    >
    </a-table>
</template>
<script>
import tableDragResize from '@/mixins/tableDragResize'
export default {
  name: 'User',
  mixins: [tableDragResize],
  data(){
  return{
   tableColumns: [
        {
          title: '用户编号',
          dataIndex: 'userId',
          ellipsis: true,
          width: 100,
        },
        {
          title: '用户名称',
          dataIndex: 'userName',
          ellipsis: true,
          width: 100,
        },
         {
          title: '操作',
          key: 'operation',
          width: 130,
          scopedSlots: { customRender: 'operation' },
        },
        ]
  }}
  }
  </script>

还有在全局哪里加上拖拽的样式

.resize-table-th {
  position: relative;
  .table-draggable-handle {
    height: 100% !important;
    bottom: 0;
    left: auto !important;
    right: -5px;
    cursor: col-resize;
    touch-action: none;
  }
}

4、注意事项:
1)若是表格有复选框的话:官网中 没有封装带复选框的情况那么这段代码会报错
Cannot read property ‘width’ of undefined

const { key, ...restProps } = props;
      const col = this.columns.find((item) => {
        const k = item.dataIndex || item.key;
        return k === key;
      });

原因是我们加了复选框后,在遍历的时候就会有一个key为‘selection-column’的列,导致了col为undefined,所以在下面的col.width的逻辑中就报错了。如果要解决此问题,只需要将这个列单独处理即可,如下:

 const { key, ...restProps } = props
    let col
    if (key === 'selection-column') {
      //表格加了复选框
      col = {}
    } else {
      col = tbCols.find((item) => {
        const k = item.dataIndex || item.key
        return k === key
      })
    }

2)还有就是表格要加bordered属性,以及colums数据中一定要加width宽度,不然会报错
3)最重要的是表格的colums数据中要加dataIndex 或者key属性,否则报错。
以上都是自己遇到的坑,血淋淋的。。。

 类似资料: