news 2026/4/17 19:36:16

Vue3.0实战:JeecgBoot项目中BasicTable父子组件联动全选功能实现(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3.0实战:JeecgBoot项目中BasicTable父子组件联动全选功能实现(附完整代码)

Vue3.0实战:JeecgBoot项目中BasicTable父子组件联动全选功能深度解析

在复杂的企业级后台系统中,表格数据的层级展示与批量操作是高频需求场景。本文将以JeecgBoot框架为基础,深入剖析Vue3.0组合式API在BasicTable组件中实现父子级联选择的完整技术方案,同时分享实际开发中的性能优化技巧和常见问题解决方案。

1. 需求分析与技术选型

1.1 业务场景还原

典型的多级表格交互通常存在以下核心需求:

  • 父级选择框勾选时自动选中所有子项
  • 子项全部选中时自动勾选父级选择框
  • 部分子项选中时父级显示半选状态
  • 支持跨层级的状态同步更新

在JeecgBoot的权限管理系统、订单处理等模块中,这类交互模式能显著提升批量操作的效率。例如:

  • 部门-员工层级管理
  • 订单-商品明细批量处理
  • 分类-子分类数据导出

1.2 技术实现对比

方案优点缺点
事件冒泡机制实现简单,适合浅层级结构深层嵌套时逻辑复杂
Vuex状态管理状态集中管理,便于调试中小项目显得臃肿
组合式API响应式引用逻辑复用性强,性能最优需要理解Vue3响应式原理

经过实际验证,我们选择基于Vue3的组合式API实现,其核心优势在于:

// 典型响应式引用声明 const parentSelectedKeys = ref([]) const childSelectedKeys = ref({})

2. 核心实现逻辑拆解

2.1 父子选择状态联动

父级选择控制子级
const handleParentSelect = (parent, selected) => { // 更新父级选中状态 parentSelectedKeys.value = selected ? [...parentSelectedKeys.value, parent.id] : parentSelectedKeys.value.filter(k => k !== parent.id) // 递归更新子级状态 const updateChildren = (children) => { children.forEach(child => { childSelectedKeys.value[parent.id] = selected ? [...new Set([...childSelectedKeys.value[parent.id] || [], child.childId])] : (childSelectedKeys.value[parent.id] || []).filter(k => k !== child.childId) if (child.children) updateChildren(child.children) }) } updateChildren(parent.children || []) }
子级选择影响父级
const handleChildSelect = (child, selected, parent) => { // 更新当前子级状态 childSelectedKeys.value[parent.id] = selected ? [...childSelectedKeys.value[parent.id] || [], child.childId] : (childSelectedKeys.value[parent.id] || []).filter(k => k !== child.childId) // 检查是否全选 const allSelected = parent.children.every(c => (childSelectedKeys.value[parent.id] || []).includes(c.childId) ) // 同步父级状态 if (allSelected && !parentSelectedKeys.value.includes(parent.id)) { parentSelectedKeys.value = [...parentSelectedKeys.value, parent.id] } else if (!allSelected && parentSelectedKeys.value.includes(parent.id)) { parentSelectedKeys.value = parentSelectedKeys.value.filter(k => k !== parent.id) } }

2.2 性能优化关键点

内存优化方案

  • 使用Map替代Object存储子级选中状态
  • 采用WeakMap管理临时计算数据
  • 实现选择状态的分级懒加载

提示:对于超大规模数据(>1000条),建议实现虚拟滚动+可视区域状态管理,可参考以下配置:

const virtualScrollOptions = { height: 600, itemSize: 54, buffer: 10 }

3. JeecgBoot集成实践

3.1 BasicTable特殊配置

JeecgBoot的BasicTable组件需要特殊处理以下属性:

const parentRowSelection = { selectedRowKeys: parentSelectedKeys, onChange: handleParentSelect, columnWidth: 40, checkStrictly: false, getCheckboxProps: record => ({ indeterminate: checkIndeterminate(record) }) }

关键参数说明

  • checkStrictly: false启用父子联动
  • indeterminate实现半选状态显示
  • columnWidth控制选择框列宽

3.2 扩展行处理技巧

对于可展开的嵌套表格,需要特别注意:

<BasicTable :expandedRowKeys="expandedRowKeys" @expand="handleExpand" > <template #expandedRowRender="{ record }"> <ChildTable :parentRecord="record" /> </template> </BasicTable>

常见问题解决方案

  1. 展开状态丢失:维护expandedRowKeys数组
  2. 子表滚动错位:固定父表列宽
  3. 性能卡顿:使用v-if替代v-show控制子表渲染

4. 企业级应用增强方案

4.1 状态持久化实现

// 使用localStorage保存选中状态 watch([parentSelectedKeys, childSelectedKeys], () => { localStorage.setItem('table-selection', JSON.stringify({ parent: parentSelectedKeys.value, children: childSelectedKeys.value })) }, { deep: true }) // 初始化时恢复状态 onMounted(() => { const saved = JSON.parse(localStorage.getItem('table-selection')) if (saved) { parentSelectedKeys.value = saved.parent childSelectedKeys.value = saved.children } })

4.2 多页签协同处理

在JeecgBoot的多页签环境中,需要处理以下特殊情况:

  • 跨页签状态同步
  • 批量操作冲突检测
  • 异步加载时的状态回填

推荐采用事件总线模式:

const eventBus = mitt() // 发送选择事件 eventBus.emit('selection-change', { tabId: currentTab.id, selection: getCurrentSelection() }) // 接收事件 eventBus.on('selection-change', (payload) => { if (payload.tabId !== currentTab.id) { // 处理跨页签逻辑 } })

5. 测试验证与异常处理

5.1 单元测试要点

describe('联动选择测试', () => { test('父选触发子选', () => { const parent = { id: 1, children: [{ childId: 101 }] } handleParentSelect(parent, true) expect(childSelectedKeys.value[1]).toContain(101) }) test('子全选触发父选', () => { const parent = { id: 1, children: [{ childId: 101 }] } handleChildSelect({ childId: 101 }, true, parent) expect(parentSelectedKeys.value).toContain(1) }) })

5.2 常见异常场景

数据不一致问题

  • 解决方案:实现状态校验函数
function validateSelection() { return parentSelectedKeys.value.every(parentId => { const children = getChildren(parentId) return children.every(child => (childSelectedKeys.value[parentId] || []).includes(child.childId) ) }) }

性能监控指标

const perfMetrics = { selectTime: 0, updateCount: 0 } function wrapWithPerf(fn) { return (...args) => { const start = performance.now() const result = fn(...args) perfMetrics.selectTime += performance.now() - start perfMetrics.updateCount++ return result } }

在项目实际落地过程中,我们发现当层级超过5层时,需要引入路径压缩算法来优化状态更新性能。通过将树形结构扁平化处理,可以使操作时间复杂度从O(n)降低到O(1)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 15:35:17

12、门禁系统接线全图解:从入门到精通,新手也能轻松上手

1. 门禁系统接线入门指南 第一次接触门禁系统接线时&#xff0c;我也是一头雾水。那些五颜六色的电线、各种专业术语&#xff0c;看起来确实让人望而生畏。但实际操作后发现&#xff0c;只要掌握几个关键点&#xff0c;家庭或小型办公室的门禁安装完全可以自己搞定。下面我就用…

作者头像 李华
网站建设 2026/4/17 19:36:14

保姆级教程:用DINO模型在COCO数据集上复现51.0 AP(基于ResNet-50)

从零实现DINO模型&#xff1a;基于ResNet-50在COCO数据集达到51.0 AP的完整指南 当我在实验室第一次看到DINO模型在COCO数据集上跑出51.0 AP时&#xff0c;那种震撼至今难忘——这个基于Transformer的检测器不仅超越了传统CNN方法的精度&#xff0c;还彻底摆脱了锚框和非极大值…

作者头像 李华
网站建设 2026/4/14 15:35:13

ESPRESSIF乐鑫 ESP32-D0WDQ6-V3 QFN48 无线收发芯片

支持IEEE802.11b/g/n协议 802.11n (2.4 GHz)速度高达150 Mbps 无线多媒体(WMM) 帧聚合(TX/RX A-MPDU,RX A-MSDU) 立即块确认(Immediate Block ACK) 重组(Defragmentation) Beacon自动监测(硬件TSF) 4个虚拟Wi-Fi接口 同时支持基础结构型网络(InfrastructureBSS)Station模式/Sof…

作者头像 李华
网站建设 2026/4/14 15:32:11

如何轻松下载在线视频:VideoDownloadHelper浏览器扩展完整指南

如何轻松下载在线视频&#xff1a;VideoDownloadHelper浏览器扩展完整指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否遇到过想保存…

作者头像 李华