Vue3后台管理系统实战:用Element Plus和Sortable.js搞定表格列顺序自定义(附完整代码)

张开发
2026/4/24 17:22:39 15 分钟阅读

分享文章

Vue3后台管理系统实战:用Element Plus和Sortable.js搞定表格列顺序自定义(附完整代码)
Vue3后台管理系统实战用Element Plus和Sortable.js实现表格列顺序自定义在后台管理系统的开发中表格是最常用的数据展示组件之一。不同角色的用户往往对表格列的显示顺序有不同的偏好——财务人员可能更关注金额数据而运营团队则更看重用户行为指标。传统的固定列排序方式已经无法满足这种个性化需求因此实现可自定义的表格列顺序成为了提升用户体验的关键功能。本文将基于Vue3、Element Plus和Sortable.js从实际业务场景出发带你实现一个完整的表格列顺序自定义解决方案。不同于简单的demo演示我们会重点考虑以下几个生产环境中的实际问题如何优雅地集成拖拽功能与现有Element表格用户偏好的持久化存储方案本地与服务器两种方式权限控制下的列可见性管理性能优化与边界情况处理1. 环境准备与基础集成1.1 初始化Vue3项目首先确保你已经创建了一个Vue3项目。如果尚未创建可以使用Vite快速初始化npm create vitelatest vue3-table-demo --template vue cd vue3-table-demo npm install接着安装必要的依赖npm install element-plus sortablejs1.2 配置Element Plus在main.js中全局引入Element Plusimport { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vue const app createApp(App) app.use(ElementPlus) app.mount(#app)2. 核心功能实现2.1 表格数据结构设计不同于简单的示例代码实际项目中我们需要更健壮的数据结构const state reactive({ // 所有可用列配置 allColumns: [ { id: date, label: 日期, visible: true, order: 1 }, { id: name, label: 姓名, visible: true, order: 2 }, { id: address, label: 地址, visible: true, order: 3 }, { id: status, label: 状态, visible: false, order: 4 } ], // 当前显示的列计算属性 visibleColumns: computed(() state.allColumns .filter(col col.visible) .sort((a, b) a.order - b.order) ), // 表格数据 tableData: [...] })2.2 拖拽功能集成使用Sortable.js实现列拖拽时需要注意Element Plus表格的特殊DOM结构import Sortable from sortablejs const setupColumnDrag () { const tableHeader document.querySelector(.el-table__header-wrapper tr) Sortable.create(tableHeader, { animation: 150, handle: .el-table__cell, onEnd: (evt) { const { oldIndex, newIndex } evt // 更新列顺序 const movedColumn state.visibleColumns[oldIndex] state.allColumns.forEach(col { if (col.id movedColumn.id) { col.order newIndex 1 } }) } }) }注意需要在表格渲染完成后如onMounted或nextTick中初始化Sortable实例3. 高级功能实现3.1 用户偏好持久化用户自定义的列顺序应该被保存避免每次刷新后重置。我们提供两种存储方案本地存储方案LocalStorageconst saveToLocalStorage () { localStorage.setItem(tableColumns, JSON.stringify(state.allColumns)) } const loadFromLocalStorage () { const saved localStorage.getItem(tableColumns) if (saved) { state.allColumns JSON.parse(saved) } }服务器存储方案const saveToServer async () { try { await api.saveUserPreferences({ tableColumns: state.allColumns }) } catch (error) { console.error(保存失败:, error) } }3.2 权限控制集成结合角色权限控制列的可见性const checkColumnVisibility (columnId) { const userRoles getUserRoles() const column state.allColumns.find(c c.id columnId) // 管理员可以看到所有列 if (userRoles.includes(admin)) return true // 其他角色根据配置决定 return column.visibleForRoles?.some(role userRoles.includes(role)) ?? true }4. 性能优化与最佳实践4.1 防抖与批量更新频繁的拖拽操作可能导致性能问题我们可以使用防抖技术优化import { debounce } from lodash-es const savePreferences debounce(() { if (useServerStorage) { saveToServer() } else { saveToLocalStorage() } }, 1000)4.2 响应式设计考虑确保自定义列功能在不同屏幕尺寸下都能良好工作/* 为拖拽手柄添加响应式样式 */ .el-table__cell .drag-handle { cursor: move; opacity: 0.5; transition: opacity 0.2s; } media (max-width: 768px) { .el-table__cell .drag-handle { padding: 4px; } }4.3 可访问性增强为拖拽操作添加ARIA属性提升无障碍体验onStart: (evt) { evt.item.setAttribute(aria-grabbed, true) }, onEnd: (evt) { evt.item.setAttribute(aria-grabbed, false) }5. 完整组件实现下面是一个可直接复用的TableCustomizer组件实现template div classtable-container el-table :datatableData border el-table-column v-forcol in visibleColumns :keycol.id :propcol.id :labelcol.label template #header div classcolumn-header {{ col.label }} i classel-icon-rank drag-handle/i /div /template /el-table-column /el-table el-dialog v-modelshowConfigDialog title表格列配置 !-- 列配置界面 -- /el-dialog /div /template script setup import { ref, reactive, computed, onMounted } from vue import Sortable from sortablejs // 组件实现... /script在实际项目中应用这个组件时我发现几个值得注意的细节在移动端触摸设备上需要增加拖拽手柄的触摸区域对于特别宽的表格考虑添加横向滚动提示列配置变化时添加平滑的过渡动画能显著提升用户体验

更多文章