当前位置:首页 > 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属性实现宽度同步:

<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属性减少重排开销:

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实现表格拖动

实现表格拖动的核心方法 使用Vue实现表格拖动功能通常涉及HTML5的拖放API或第三方库。以下是两种常见实现方式: 基于HTML5原生拖放API 在Vue组件中绑定拖放事件实现基础功能: &…

vue拖动实现

vue拖动实现

实现 Vue 拖动功能的方法 使用 HTML5 拖放 API 在 Vue 中可以利用 HTML5 的原生拖放 API 实现拖动功能。通过 draggable 属性标记可拖动元素,结合 @dragsta…

css 制作表格

css 制作表格

基础表格结构 使用HTML的<table>标签创建表格框架,搭配<tr>(行)、<th>(表头)和<td>(单元格)标签。例如: <table…

css表格制作表格

css表格制作表格

CSS 表格制作方法 使用 CSS 创建表格可以通过多种方式实现,包括原生 HTML 表格元素结合 CSS 样式,或者使用纯 CSS 布局技术(如 Flexbox 或 Grid)模拟表格效果。以下是常…

css制作表格

css制作表格

使用HTML和CSS创建表格 HTML中的<table>元素用于创建表格,结合CSS可以调整样式。以下是一个基础示例: <table> <tr> &l…

用css制作表格

用css制作表格

使用CSS制作表格 CSS可以用来样式化HTML表格,使其更具视觉吸引力和功能性。以下是几种常见的方法: 基础表格样式 通过CSS可以调整表格的边框、间距和颜色: <table>…