vue-resizable-table
v1.0.6
Published
A Vue 3 component for resizable and draggable table columns with ViewUI
Maintainers
Readme
ResizableTable
一个功能强大的 Vue 3 可调整列宽表格组件,支持列拖拽排序、字段选择、自动保存配置等功能。
特性
- 🎯 列宽调整: 支持拖拽调整列宽,自动保存配置
- 🔄 列拖拽排序: 支持拖拽交换列位置,实时预览效果
- 👁️ 字段选择: 支持动态显示/隐藏列,灵活控制表格展示
- 💾 配置持久化: 自动保存列宽、顺序、可见性配置到本地存储
- 📱 响应式设计: 支持窗口大小变化时自动调整列宽
- 🎨 美观界面: 现代化 UI 设计,丰富的视觉反馈
- ⚡ 高性能: 优化的拖拽算法,流畅的交互体验
- 🔧 高度可配置: 丰富的配置选项,满足各种使用场景
安装
npm install resizable-table-vue使用
基础用法
<template>
<ResizableTable
:data="tableData"
:columns="columns"
:total="total"
:current-page="currentPage"
:page-size="pageSize"
:loading="loading"
title="用户列表"
@on-page-change="handlePageChange"
@on-page-size-change="handlePageSizeChange"
@on-column-resize="handleColumnResize"
@on-column-reorder="handleColumnReorder"
@on-selection-change="handleSelectionChange"
/>
</template>
<script setup>
import { ref } from 'vue'
import ResizableTable from 'resizable-table-vue'
const tableData = ref([
{ id: 1, name: '张三', age: 25, email: '[email protected]', status: 'active' },
{ id: 2, name: '李四', age: 30, email: '[email protected]', status: 'inactive' },
{ id: 3, name: '王五', age: 28, email: '[email protected]', status: 'active' }
])
const columns = ref([
{
key: 'id',
title: 'ID',
width: 80,
sortable: true,
resizable: true,
draggable: true
},
{
key: 'name',
title: '姓名',
minWidth: 120,
sortable: true,
resizable: true,
draggable: true
},
{
key: 'age',
title: '年龄',
width: 100,
sortable: true,
resizable: true,
draggable: true
},
{
key: 'email',
title: '邮箱',
minWidth: 200,
resizable: true,
draggable: true
},
{
key: 'status',
title: '状态',
width: 120,
resizable: true,
draggable: true,
render: (h, { row }) => {
const color = row.status === 'active' ? 'success' : 'error'
const text = row.status === 'active' ? '激活' : '禁用'
return h('Tag', { props: { color } }, text)
}
},
{
key: 'action',
title: '操作',
width: 180,
resizable: true,
draggable: false, // 操作列通常不允许拖拽
render: (h, { row }) => {
return h('div', [
h('Button', {
props: { type: 'primary', size: 'small' },
style: { marginRight: '8px' },
on: { click: () => handleEdit(row) }
}, '编辑'),
h('Button', {
props: { type: 'error', size: 'small' },
on: { click: () => handleDelete(row) }
}, '删除')
])
}
}
])
const total = ref(100)
const currentPage = ref(1)
const pageSize = ref(10)
const loading = ref(false)
const handlePageChange = (page) => {
currentPage.value = page
// 加载数据逻辑
loadData()
}
const handlePageSizeChange = (size) => {
pageSize.value = size
currentPage.value = 1
// 加载数据逻辑
loadData()
}
const handleColumnResize = ({ column, width, deltaX }) => {
console.log(`列 ${column.title} 宽度调整为: ${width}px`)
}
const handleColumnReorder = ({ fromIndex, toIndex, newOrder, action }) => {
console.log(`列从位置 ${fromIndex} 移动到位置 ${toIndex}`)
}
const handleSelectionChange = (selection) => {
console.log('选中的行:', selection)
}
const handleEdit = (row) => {
console.log('编辑:', row)
}
const handleDelete = (row) => {
console.log('删除:', row)
}
const loadData = () => {
loading.value = true
// 模拟API调用
setTimeout(() => {
loading.value = false
}, 1000)
}
</script>全局注册
import { createApp } from 'vue'
import ResizableTable from 'resizable-table-vue'
const app = createApp(App)
app.use(ResizableTable)API
Props
| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | data | Array | [] | 表格数据 | | columns | Array | [] | 表格列配置 | | loading | Boolean | false | 加载状态 | | title | String | '' | 表格标题 | | total | Number | 0 | 数据总数 | | currentPage | Number | 1 | 当前页码 | | pageSize | Number | 10 | 每页条数 | | border | Boolean | true | 是否显示边框 | | stripe | Boolean | true | 是否显示斑马纹 | | height | Number/String | null | 表格高度 | | maxHeight | Number/String | null | 表格最大高度 | | showHeader | Boolean | true | 是否显示表头 | | size | String | 'default' | 表格尺寸 (large/default/small) | | noDataText | String | '暂无数据' | 无数据时显示的文本 | | noFilteredDataText | String | '暂无筛选结果' | 无筛选结果时显示的文本 | | showToolbar | Boolean | true | 是否显示工具栏 | | showPagination | Boolean | true | 是否显示分页器 | | pageSizeOpts | Array | [10, 20, 50, 100] | 每页条数选择器的选项 | | showTotal | Boolean | true | 是否显示总数 | | showElevator | Boolean | true | 是否显示电梯(快速跳转) | | showSizer | Boolean | true | 是否显示分页大小选择器 | | showQuickJumper | Boolean | false | 是否显示快速跳转 | | paginationSize | String | 'default' | 分页器尺寸 | | simple | Boolean | false | 是否使用简洁分页器 | | placement | String | 'bottom' | 分页器位置 | | storageKey | String | 'resizable-table-columns' | 本地存储键名 | | minWidth | Number | 300 | 最小列宽 |
Column 配置
| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | key | String | - | 列标识 | | title | String | - | 列标题 | | width | Number | - | 列宽度 | | minWidth | Number | 120 | 最小宽度 | | resizable | Boolean | true | 是否可调整大小 | | draggable | Boolean | true | 是否可拖拽排序 | | sortable | Boolean | false | 是否可排序 | | filterable | Boolean | false | 是否可过滤 | | align | String | 'left' | 对齐方式 | | fixed | String | - | 固定列 (left/right) | | render | Function | - | 自定义渲染函数 | | slot | String | - | 插槽名称 |
Events
| 事件名 | 参数 | 说明 | |--------|------|------| | on-select | selection, row | 在多选模式下,选中某一项时触发 | | on-select-cancel | selection, row | 在多选模式下,取消选中某一项时触发 | | on-select-all | selection | 在多选模式下,点击全选时触发 | | on-select-all-cancel | selection | 在多选模式下,点击取消全选时触发 | | on-selection-change | selection | 在多选模式下,只要选中项发生变化时就会触发 | | on-sort-change | column | 排序变化时触发 | | on-filter-change | filters | 过滤变化时触发 | | on-row-click | row, index | 点击行时触发 | | on-row-dblclick | row, index | 双击行时触发 | | on-expand | row, status | 展开或收起某一行时触发 | | on-expand-change | expandedRows | 展开的行发生变化时触发 | | on-current-change | currentRow, oldCurrentRow | 当前行发生变化时触发 | | on-page-change | page | 页码变化时触发 | | on-page-size-change | pageSize | 每页条数变化时触发 | | on-column-resize | { column, width, deltaX } | 列宽调整时触发 | | on-column-reorder | { fromIndex, toIndex, newOrder, action } | 列排序变化时触发 |
高级功能
列宽调整
组件支持拖拽调整列宽,调整后的宽度会自动保存到本地存储。
<ResizableTable
:columns="columns"
:min-width="100"
storage-key="my-table-config"
@on-column-resize="handleColumnResize"
/>特性说明:
- 鼠标悬停在列边界时显示调整光标
- 支持设置最小列宽限制
- 自动保存调整后的列宽到本地存储
- 支持重置列宽功能
列拖拽排序
支持拖拽交换列位置,提供实时预览效果。
<ResizableTable
:columns="columns"
@on-column-reorder="handleColumnReorder"
/>特性说明:
- 拖拽时显示视觉反馈和指示器
- 实时预览拖拽效果
- 支持禁用特定列的拖拽功能
- 自动保存列顺序到本地存储
字段选择
用户可以动态选择显示哪些列。
<ResizableTable
:columns="columns"
:show-toolbar="true"
/>特性说明:
- 工具栏提供字段选择按钮
- 支持全选/取消全选功能
- 显示已选择字段数量统计
- 自动保存字段可见性设置
配置持久化
组件会自动将用户的配置保存到本地存储,包括:
- 列宽设置:每列的宽度调整
- 列顺序:拖拽后的列排序
- 字段可见性:显示/隐藏的列设置
<ResizableTable
storage-key="my-custom-table-config"
:columns="columns"
/>配置管理:
- 使用
localStorage进行持久化存储 - 支持自定义存储键名
- 提供手动保存和自动保存功能
- 支持重置所有配置
工具栏功能
组件提供了丰富的工具栏功能:
<ResizableTable
:show-toolbar="true"
title="数据列表"
:total="100"
/>工具栏包含:
- 表格标题:显示表格名称
- 数据统计:显示总记录数
- 重置列宽:一键重置所有列宽
- 选择字段:打开字段选择弹窗
- 保存设置:手动保存当前配置
响应式设计
组件支持响应式布局,在不同屏幕尺寸下自动调整:
/* 移动端适配 */
@media (max-width: 768px) {
.table-toolbar {
flex-direction: column;
}
.pagination-wrapper {
text-align: center;
}
}自定义渲染
支持自定义列内容渲染。
const columns = [
{
key: 'status',
title: '状态',
render: (h, { row }) => {
const color = row.status === 'active' ? 'success' : 'error'
return h('Tag', { props: { color } }, row.status)
}
}
]插槽支持
支持使用插槽自定义列内容。
<ResizableTable :columns="columns">
<template #status="{ row }">
<Tag :color="row.status === 'active' ? 'success' : 'error'">
{{ row.status }}
</Tag>
</template>
</ResizableTable>多选功能
组件完整支持表格的多选功能:
<ResizableTable
:columns="columnsWithSelection"
@on-selection-change="handleSelectionChange"
@on-select-all="handleSelectAll"
/>多选特性:
- 支持单行选择和全选
- 提供选择状态变化事件
- 支持取消选择操作
- 选择状态实时反馈
展开行功能
支持表格行的展开和收起:
<ResizableTable
:columns="columns"
@on-expand="handleExpand"
@on-expand-change="handleExpandChange"
/>方法
| 方法名 | 说明 | 参数 | |--------|------|------| | resetColumnWidths | 重置所有列宽到默认值 | - | | saveSettings | 手动保存当前配置到本地存储 | - | | showFieldSelector | 显示字段选择弹窗 | - | | hideFieldSelector | 隐藏字段选择弹窗 | - | | selectAllFields | 全选所有字段 | - | | unselectAllFields | 取消全选所有字段 | - | | applyFieldSelection | 应用字段选择 | - | | cancelFieldSelection | 取消字段选择 | - |
插槽
| 插槽名 | 说明 | 参数 | |--------|------|------| | default | 表格列内容插槽 | { row, column, index } | | [column.key] | 特定列的内容插槽 | { row, column, index } | | toolbar-left | 工具栏左侧自定义内容 | - | | toolbar-right | 工具栏右侧自定义内容 | - | | empty | 空数据时的自定义内容 | - |
配置存储
组件使用 localStorage 来持久化用户配置,存储的数据结构如下:
{
columnWidths: {
[columnKey]: width // 列宽设置
},
columnOrder: [columnKey1, columnKey2, ...], // 列顺序
visibleColumns: {
[columnKey]: boolean // 列可见性
}
}存储键名规则:
- 默认键名:
resizable-table-config - 自定义键名:通过
storage-keyprop 设置 - 完整键名:
${storageKey}-${configType}
配置类型:
widths:列宽配置order:列顺序配置visibility:列可见性配置
组件提供了丰富的 CSS 类名,可以轻松定制样式。
/* 自定义表格样式 */
.resizable-table-container {
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* 自定义工具栏样式 */
.table-toolbar {
background: linear-gradient(90deg, #f8f9fa 0%, #e9ecef 100%);
}
/* 自定义拖拽样式 */
.drag-indicator {
background: linear-gradient(180deg, #28a745 0%, #20c997 100%);
}浏览器兼容性
- Chrome >= 60
- Firefox >= 60
- Safari >= 12
- Edge >= 79
依赖
- Vue 3.0+
- View UI Plus (iView)
许可证
MIT License
更新日志
1.0.1
- 初始版本发布
- 支持列宽调整
- 支持列拖拽排序
- 支持字段选择
- 支持配置持久化
效果展示
列宽调整

拖拽调整列宽
列排序

拖拽交换列位置
字段选择

