当前位置: 首页 > news >正文

别再复制粘贴了!Element Plus 表格组件与SpringBoot后端数据联调实战

别再复制粘贴了Element Plus 表格组件与SpringBoot后端数据联调实战在前后端分离的开发模式中前端表格组件与后端数据的动态联调是每个开发者必须掌握的技能。Element Plus作为Vue3生态中最受欢迎的UI组件库之一其表格组件(el-table)的灵活性和功能性备受推崇。然而很多开发者在从静态Demo转向真实项目时往往会遇到数据绑定、异步加载、分页联动等一系列挑战。本文将带你从零开始彻底解决这些问题。1. 环境准备与基础配置在开始之前确保你已经搭建好以下开发环境Vue3项目推荐使用Vite创建Element Plus已正确安装并引入SpringBoot后端API服务已就绪首先需要在Vue项目中安装axios这是与后端通信的基础工具npm install axios接着在src目录下创建一个名为api的文件夹用于存放所有与API相关的配置和请求方法。在api文件夹中创建index.js文件配置axios实例import axios from axios const service axios.create({ baseURL: http://your-api-domain.com/api, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use( config { // 在这里可以添加token等认证信息 return config }, error { return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response { return response.data }, error { return Promise.reject(error) } ) export default service2. 解决跨域问题在开发阶段前端项目和后端API通常运行在不同的端口上这会导致跨域问题。有两种常见的解决方案2.1 后端配置CORS在SpringBoot应用中可以通过添加CORS配置类来解决Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .maxAge(3600); } }2.2 前端代理配置如果你使用Vite可以在vite.config.js中配置代理export default defineConfig({ server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } } })3. 实现表格数据动态加载现在我们来实现表格数据的动态加载功能。首先创建一个Vue组件命名为DataTable.vuetemplate el-table :datatableData v-loadingloading stylewidth: 100% empty-text暂无数据 el-table-column propid labelID width180 / el-table-column propname label姓名 width180 / el-table-column propemail label邮箱 / /el-table /template script setup import { ref, onMounted } from vue import api from /api const tableData ref([]) const loading ref(false) const fetchData async () { try { loading.value true const response await api.get(/users) tableData.value response.data } catch (error) { console.error(获取数据失败:, error) // 这里可以添加更详细的错误处理逻辑 } finally { loading.value false } } onMounted(() { fetchData() }) /script这段代码实现了以下功能使用ref创建响应式数据tableData和loading状态定义异步函数fetchData来获取后端数据在onMounted生命周期钩子中调用fetchData使用v-loading指令显示加载状态通过empty-text属性设置空数据提示4. 分页功能实现实际项目中数据量通常很大需要实现分页功能。Element Plus提供了el-pagination组件我们可以轻松实现分页template div el-table :datatableData v-loadingloading stylewidth: 100% empty-text暂无数据 !-- 表格列定义 -- /el-table el-pagination v-model:current-pagecurrentPage v-model:page-sizepageSize :totaltotal :page-sizes[10, 20, 50, 100] layouttotal, sizes, prev, pager, next, jumper size-changehandleSizeChange current-changehandleCurrentChange / /div /template script setup import { ref, onMounted } from vue import api from /api const tableData ref([]) const loading ref(false) const currentPage ref(1) const pageSize ref(10) const total ref(0) const fetchData async () { try { loading.value true const response await api.get(/users, { params: { page: currentPage.value, size: pageSize.value } }) tableData.value response.data.items total.value response.data.total } catch (error) { console.error(获取数据失败:, error) } finally { loading.value false } } const handleSizeChange (val) { pageSize.value val fetchData() } const handleCurrentChange (val) { currentPage.value val fetchData() } onMounted(() { fetchData() }) /script后端SpringBoot接口需要支持分页参数通常使用Spring Data JPA的PageableGetMapping(/users) public ResponseEntityPageUser getUsers( RequestParam(defaultValue 0) int page, RequestParam(defaultValue 10) int size) { Pageable pageable PageRequest.of(page - 1, size); PageUser userPage userRepository.findAll(pageable); return ResponseEntity.ok(userPage); }5. 高级功能实现5.1 表格排序Element Plus表格支持排序功能我们可以轻松实现前后端联动的排序el-table :datatableData sort-changehandleSortChange el-table-column propname label姓名 sortablecustom / !-- 其他列 -- /el-table script setup // ...其他代码 const sortProp ref() const sortOrder ref() const handleSortChange ({ prop, order }) { sortProp.value prop sortOrder.value order ascending ? asc : order descending ? desc : fetchData() } const fetchData async () { try { loading.value true const params { page: currentPage.value, size: pageSize.value } if (sortProp.value sortOrder.value) { params.sort ${sortProp.value},${sortOrder.value} } const response await api.get(/users, { params }) tableData.value response.data.items total.value response.data.total } catch (error) { console.error(获取数据失败:, error) } finally { loading.value false } } /script后端接口需要相应支持排序参数GetMapping(/users) public ResponseEntityPageUser getUsers( RequestParam(defaultValue 0) int page, RequestParam(defaultValue 10) int size, RequestParam(required false) String sort) { Pageable pageable; if (sort ! null !sort.isEmpty()) { String[] sortParams sort.split(,); Sort.Direction direction Sort.Direction.fromString(sortParams[1]); pageable PageRequest.of(page - 1, size, Sort.by(direction, sortParams[0])); } else { pageable PageRequest.of(page - 1, size); } PageUser userPage userRepository.findAll(pageable); return ResponseEntity.ok(userPage); }5.2 表格筛选实现表格列的筛选功能可以大大提升用户体验template el-table-column propstatus label状态 template #header div styledisplay: flex; align-items: center; span状态/span el-select v-modelstatusFilter placeholder筛选 stylewidth: 100px; margin-left: 10px; changehandleFilterChange el-option label全部 value / el-option label激活 valueactive / el-option label禁用 valueinactive / /el-select /div /template /el-table-column /template script setup const statusFilter ref() const handleFilterChange () { currentPage.value 1 // 重置到第一页 fetchData() } const fetchData async () { try { loading.value true const params { page: currentPage.value, size: pageSize.value, status: statusFilter.value } if (sortProp.value sortOrder.value) { params.sort ${sortProp.value},${sortOrder.value} } const response await api.get(/users, { params }) tableData.value response.data.items total.value response.data.total } catch (error) { console.error(获取数据失败:, error) } finally { loading.value false } } /script后端接口需要增加状态筛选参数GetMapping(/users) public ResponseEntityPageUser getUsers( RequestParam(defaultValue 0) int page, RequestParam(defaultValue 10) int size, RequestParam(required false) String sort, RequestParam(required false) String status) { Pageable pageable; if (sort ! null !sort.isEmpty()) { String[] sortParams sort.split(,); Sort.Direction direction Sort.Direction.fromString(sortParams[1]); pageable PageRequest.of(page - 1, size, Sort.by(direction, sortParams[0])); } else { pageable PageRequest.of(page - 1, size); } SpecificationUser spec (root, query, cb) - { ListPredicate predicates new ArrayList(); if (status ! null !status.isEmpty()) { predicates.add(cb.equal(root.get(status), status)); } return cb.and(predicates.toArray(new Predicate[0])); }; PageUser userPage userRepository.findAll(spec, pageable); return ResponseEntity.ok(userPage); }6. 错误处理与用户体验优化良好的错误处理和用户体验是专业应用的关键。我们可以从以下几个方面进行优化6.1 增强错误处理const fetchData async () { try { loading.value true const params { page: currentPage.value, size: pageSize.value, status: statusFilter.value } if (sortProp.value sortOrder.value) { params.sort ${sortProp.value},${sortOrder.value} } const response await api.get(/users, { params }) tableData.value response.data.items total.value response.data.total } catch (error) { console.error(获取数据失败:, error) ElMessage.error({ message: 获取数据失败请稍后重试, duration: 3000 }) // 重置数据避免显示错误内容 tableData.value [] total.value 0 } finally { loading.value false } }6.2 添加重试机制const retryCount ref(0) const MAX_RETRY 3 const fetchData async () { try { loading.value true const params { page: currentPage.value, size: pageSize.value, status: statusFilter.value } if (sortProp.value sortOrder.value) { params.sort ${sortProp.value},${sortOrder.value} } const response await api.get(/users, { params }) tableData.value response.data.items total.value response.data.total retryCount.value 0 // 成功时重置重试计数 } catch (error) { console.error(获取数据失败:, error) if (retryCount.value MAX_RETRY) { retryCount.value setTimeout(() { fetchData() }, 1000 * retryCount.value) // 指数退避 return } ElMessage.error({ message: 获取数据失败请稍后重试, duration: 3000 }) tableData.value [] total.value 0 retryCount.value 0 } finally { loading.value false } }6.3 添加数据缓存为了提高性能我们可以添加简单的数据缓存const cache ref(new Map()) const fetchData async () { try { loading.value true const cacheKey JSON.stringify({ page: currentPage.value, size: pageSize.value, status: statusFilter.value, sort: sortProp.value ? ${sortProp.value},${sortOrder.value} : }) // 检查缓存 if (cache.value.has(cacheKey)) { const cachedData cache.value.get(cacheKey) tableData.value cachedData.items total.value cachedData.total return } const params { page: currentPage.value, size: pageSize.value, status: statusFilter.value } if (sortProp.value sortOrder.value) { params.sort ${sortProp.value},${sortOrder.value} } const response await api.get(/users, { params }) tableData.value response.data.items total.value response.data.total // 更新缓存 cache.value.set(cacheKey, { items: response.data.items, total: response.data.total }) retryCount.value 0 } catch (error) { // 错误处理逻辑... } finally { loading.value false } }7. 性能优化与最佳实践在实际项目中表格性能优化至关重要特别是当数据量较大时。以下是一些实用的优化技巧7.1 虚拟滚动对于大型数据集可以使用Element Plus的虚拟滚动功能el-table :datatableData height500 v-loadingloading stylewidth: 100% empty-text暂无数据 :row-height50 :virtual-scroll-options{ height: 500 } !-- 表格列定义 -- /el-table7.2 按需加载列对于列数较多的表格可以动态控制列的显示template div el-checkbox-group v-modelvisibleColumns el-checkbox v-forcolumn in allColumns :keycolumn.prop :labelcolumn.prop {{ column.label }} /el-checkbox /el-checkbox-group el-table :datatableData el-table-column v-forcolumn in filteredColumns :keycolumn.prop :propcolumn.prop :labelcolumn.label / /el-table /div /template script setup const allColumns [ { prop: id, label: ID }, { prop: name, label: 姓名 }, { prop: email, label: 邮箱 }, { prop: phone, label: 电话 }, { prop: address, label: 地址 } ] const visibleColumns ref([id, name, email]) const filteredColumns computed(() { return allColumns.filter(column visibleColumns.value.includes(column.prop)) }) /script7.3 请求防抖对于频繁触发的操作如筛选条件变化添加防抖可以避免不必要的请求import { debounce } from lodash-es const handleFilterChange debounce(() { currentPage.value 1 fetchData() }, 300)7.4 数据预处理有时后端返回的数据格式可能不适合直接显示我们可以进行预处理const fetchData async () { try { loading.value true const response await api.get(/users) // 数据预处理 tableData.value response.data.map(item ({ ...item, fullName: ${item.firstName} ${item.lastName}, formattedDate: formatDate(item.createdAt) })) } catch (error) { // 错误处理 } finally { loading.value false } } function formatDate(dateString) { const date new Date(dateString) return date.toLocaleDateString() }在实际项目中我发现合理使用这些优化技巧可以显著提升表格组件的性能和用户体验。特别是在处理大型数据集时虚拟滚动和按需加载列能带来明显的性能提升。
http://www.zskr.cn/news/1345381.html

相关文章:

  • 大麦网自动抢票终极指南:3步搞定热门演出门票
  • 终极LaTeX书籍排版指南:如何用ElegantBook打造专业学术著作
  • 终极原神帧率解锁指南:3步突破60FPS限制,畅享丝滑游戏体验
  • 如何免费下载B站4K大会员视频:终极指南与一键配置教程
  • 信息学奥赛启蒙别踩坑:GoC画图练习题的正确打开方式(附2018年模拟题解析)
  • 79、CAN总线现场抗干扰测试方法:频谱分析与眼图评估
  • 京东e卡回收折扣多少?2026正规平台推荐,92折起实时到账 - 可可收公众号
  • 09_AI审计平台设计:从风险识别出发而非从底稿编号出发
  • Minimax WebSocket TTS 文档里 bitrate / sample_rate 的真实取值
  • 2026沈阳钻石变现好去处,多家正规门店实力客观对比 - 李宏哲1
  • 告别手动对照!用OrCAD Design Sync功能,5分钟自动化同步你的原理图与Allegro PCB变更
  • 如何用Python自动化脚本高效抢购热门演出门票?智能抢票解决方案揭秘
  • U8 ERP接口二次封装实战:用Net4.8+WebAPI打造比OpenAPI更香的内网集成方案
  • 广东鸿胜金属设备回收:汕头废旧金属回收排名哪家好 - LYL仔仔
  • 2026年无锡黄金变现去哪?这 5 家正规回收店,手镯项链金条都收 - 奢侈品回收测评
  • 蛋白质结构预测模型的量化优化与硬件加速
  • 如何快速使用R3nzSkin国服换肤工具:免费解锁英雄联盟全皮肤终极教程
  • 从‘废弃信号’到规范DBC:避坑指南教你清理Vector CANdb++自动生成的0xC0000000报文
  • 【深度洞察】2026年制造业招投标智能化全流程的最新发展趋势?企业级Agent解决方案全解析
  • 5CGTFD7D5F27C7N、支持550MHz全局时钟与287MHz DSP处理的高性能FPGA
  • Java小白也能看懂!用100行代码手写Self-Attention,收藏这份AI进阶指南
  • 5月最新10款降AI神器实测:哪个能降知网维普AI率,从99.5%降至3.8%可信吗?
  • 八大网盘直链解析神器:如何彻底告别下载限速的终极指南
  • 如何用 “STAR 法则” 写项目经验,让 HR 眼前一亮
  • 别再手动调图了!用LaTeX的subcaption包搞定论文子图排版(附完整代码)
  • Agent Skills 万千应用 · 第04篇 Excel 分析 Skill:让 Agent 会整理表格、建公式、画图表
  • UE5性能优化实战:从RenderDoc截图到GPU瓶颈定位,手把手教你分析并解决卡顿
  • 在OpenClaw项目中配置Taotoken作为统一的AI能力提供方
  • 在OpenClaw项目中配置Taotoken作为统一的AI能力提供方
  • 东莞热门中央空调门店排行:品牌资质与服务能力对比 - 奔跑123