当前位置:首页 > 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>

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

相关文章

怎么制作css表格

怎么制作css表格

使用HTML和CSS创建表格 HTML提供<table>标签用于创建表格结构,CSS用于控制样式。以下是一个基础示例: <table class="styled-table">…

vue实现拖动图片验证

vue实现拖动图片验证

Vue 实现拖动图片验证功能 核心思路 拖动图片验证通常需要用户将图片拖动到指定区域或按正确顺序排列。实现时需要处理拖拽事件、验证逻辑和视觉反馈。 实现步骤 1. 基础组件结构 <tem…

h5实现表格样式

h5实现表格样式

实现H5表格样式的方法 使用HTML和CSS创建基础表格 在HTML中,表格通过<table>标签定义,配合<tr>(行)、<td>(单元格)和<th>…

vue实现表格复选

vue实现表格复选

实现表格复选的基本思路 在Vue中实现表格复选功能,通常需要结合v-model绑定选中状态,监听复选框变化事件,以及维护一个选中项的数组。以下是具体实现方法: 基础实现步骤 数据准备 定义表格数据…

css怎么制作表格

css怎么制作表格

使用HTML和CSS制作表格 在HTML中,表格由<table>标签定义,结合CSS可以灵活控制样式。 基本HTML结构: <table> <tr>…

用vue实现表格

用vue实现表格

Vue 表格实现方法 基础表格实现 使用 Vue 的 v-for 指令可以轻松渲染表格数据。准备一个数据数组,在模板中用 v-for 循环渲染。 <template> <tab…