当前位置:首页 > VUE

vue实现表格拖动列宽

2026-01-12 07:25:40VUE

实现表格列宽拖动的核心思路

通过监听鼠标事件(mousedown、mousemove、mouseup)实现拖拽逻辑,动态修改列宽。需要处理表头与表体的联动,确保拖动时视觉一致。

基础HTML结构

<template>
  <div class="draggable-table">
    <table>
      <thead>
        <tr>
          <th v-for="(col, index) in columns" :key="index" 
              @mousedown="startResize(index, $event)">
            {{ col.title }}
            <div class="resize-handle"></div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, rowIndex) in data" :key="rowIndex">
          <td v-for="(col, colIndex) in columns" :key="colIndex">
            {{ row[col.key] }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

CSS样式关键部分

.resize-handle {
  position: absolute;
  right: 0;
  top: 0;
  width: 5px;
  height: 100%;
  background: transparent;
  cursor: col-resize;
}

th {
  position: relative;
  user-select: none;
}

table {
  border-collapse: collapse;
  width: 100%;
}

td, th {
  border: 1px solid #ddd;
  padding: 8px;
}

JavaScript核心逻辑

export default {
  data() {
    return {
      columns: [
        { title: '姓名', key: 'name', width: 150 },
        { title: '年龄', key: 'age', width: 100 },
        { title: '地址', key: 'address', width: 300 }
      ],
      data: [
        { name: '张三', age: 25, address: '北京' },
        { name: '李四', age: 30, address: '上海' }
      ],
      isResizing: false,
      startX: 0,
      startWidth: 0,
      resizeIndex: null
    }
  },
  methods: {
    startResize(index, e) {
      this.isResizing = true
      this.resizeIndex = index
      this.startX = e.clientX
      this.startWidth = this.columns[index].width

      document.addEventListener('mousemove', this.handleResize)
      document.addEventListener('mouseup', this.stopResize)
    },
    handleResize(e) {
      if (!this.isResizing) return
      const newWidth = this.startWidth + (e.clientX - this.startX)
      this.columns[this.resizeIndex].width = Math.max(30, newWidth)
    },
    stopResize() {
      this.isResizing = false
      document.removeEventListener('mousemove', this.handleResize)
      document.removeEventListener('mouseup', this.stopResize)
    }
  }
}

动态绑定列宽

在HTML中绑定style属性实现宽度同步:

vue实现表格拖动列宽

<th v-for="(col, index) in columns" :key="index" 
    :style="{ width: col.width + 'px' }"
    @mousedown="startResize(index, $event)">
  {{ col.title }}
  <div class="resize-handle"></div>
</th>

<td v-for="(col, colIndex) in columns" :key="colIndex"
    :style="{ width: columns[colIndex].width + 'px' }">
  {{ row[col.key] }}
</td>

性能优化建议

使用CSS的will-change: width属性减少重排开销:

vue实现表格拖动列宽

th, td {
  will-change: width;
}

添加拖动时的视觉反馈:

.is-resizing {
  background-color: #f0f0f0;
}

在拖动时动态添加class:

handleResize(e) {
  if (!this.isResizing) return
  document.body.classList.add('is-resizing')
  // ...原有逻辑
},
stopResize() {
  document.body.classList.remove('is-resizing')
  // ...原有逻辑
}

完整组件示例

<template>
  <div class="draggable-table">
    <table>
      <thead>
        <tr>
          <th v-for="(col, index) in columns" :key="index" 
              :style="{ width: col.width + 'px' }"
              @mousedown="startResize(index, $event)">
            {{ col.title }}
            <div class="resize-handle"></div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, rowIndex) in data" :key="rowIndex">
          <td v-for="(col, colIndex) in columns" :key="colIndex"
              :style="{ width: columns[colIndex].width + 'px' }">
            {{ row[col.key] }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      columns: [
        { title: '姓名', key: 'name', width: 150 },
        { title: '年龄', key: 'age', width: 100 },
        { title: '地址', key: 'address', width: 300 }
      ],
      data: [
        { name: '张三', age: 25, address: '北京' },
        { name: '李四', age: 30, address: '上海' }
      ],
      isResizing: false,
      startX: 0,
      startWidth: 0,
      resizeIndex: null
    }
  },
  methods: {
    startResize(index, e) {
      if (e.target.classList.contains('resize-handle') || e.offsetX > this.columns[index].width - 10) {
        this.isResizing = true
        this.resizeIndex = index
        this.startX = e.clientX
        this.startWidth = this.columns[index].width
        document.addEventListener('mousemove', this.handleResize)
        document.addEventListener('mouseup', this.stopResize)
      }
    },
    handleResize(e) {
      if (!this.isResizing) return
      document.body.classList.add('is-resizing')
      const newWidth = this.startWidth + (e.clientX - this.startX)
      this.$set(this.columns, this.resizeIndex, {
        ...this.columns[this.resizeIndex],
        width: Math.max(30, newWidth)
      })
    },
    stopResize() {
      document.body.classList.remove('is-resizing')
      this.isResizing = false
      document.removeEventListener('mousemove', this.handleResize)
      document.removeEventListener('mouseup', this.stopResize)
    }
  }
}
</script>

标签: 拖动表格
分享给朋友:

相关文章

vue动态表格实现

vue动态表格实现

Vue动态表格实现方法 使用v-for指令渲染动态数据 通过v-for指令可以循环遍历数组数据生成表格行,数据变化时表格自动更新。示例代码: <template> <table…

vue实现表格滑动

vue实现表格滑动

Vue实现表格滑动的方法 使用CSS overflow属性实现横向滑动 在表格外层容器设置overflow-x: auto,限制表格宽度超出时出现滚动条。这种方法适合简单场景,无需额外依赖库。 &l…

vue实现表格输出

vue实现表格输出

Vue 实现表格输出的方法 使用原生表格标签 在 Vue 模板中可以直接使用 HTML 原生表格标签(<table>、<tr>、<td>等)渲染数据。通过 v-fo…

vue实现表格计算

vue实现表格计算

Vue 表格计算实现方法 使用计算属性 在 Vue 中可以通过计算属性来实现表格数据的动态计算。计算属性会自动缓存结果,只有当依赖的数据发生变化时才会重新计算。 computed: { tota…

vue实现拖动功能

vue实现拖动功能

使用HTML5拖放API实现基础拖动 Vue中可以通过HTML5原生拖放API实现基础拖动功能。在元素上添加draggable="true"属性使其可拖动,通过@dragstart事件设置被拖拽数据。…

vue 实现excel表格

vue 实现excel表格

Vue 实现 Excel 表格功能 在 Vue 中实现 Excel 表格功能可以通过多种方式完成,包括使用第三方库或手动实现基础功能。以下是几种常见方法: 使用 xlsx 库处理 Excel 数据…