如何在Vaadin 23 Grid中实现多层级图书数据展示与编辑
在线图书馆图书列表展示与编辑方案建议
需求说明
- 需展示最多数千条按年份排序的历史小说数据,由Web服务提供
- 数据字段繁杂,需采用多行折叠结构实现多层级展示(如主图书信息→详情→读者评论的层级折叠)
- 支持部分字段编辑:读者可编辑/删除自己的评论
- 曾考虑TreeGrid(因要求所有项为同一类放弃),现评估Grid+Accordion组合的可行性
Book实体类代码
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION, defaultImpl = Book.class) @JsonSubTypes(@JsonSubTypes.Type(value = Series.class)) public class Book implements Serializable { private static final long serialVersionUID = 1L; @JsonInclude(JsonInclude.Include.NON_NULL) private String bookId; @JsonInclude(JsonInclude.Include.NON_NULL) private List<Author> authors; @JsonInclude(JsonInclude.Include.NON_NULL) private String title; @JsonInclude(JsonInclude.Include.NON_NULL) private String url; @JsonInclude(JsonInclude.Include.NON_NULL) private Date publishedOn; @JsonInclude(JsonInclude.Include.NON_NULL) private String isbn; @JsonIgnore private Date addedOn; @JsonInclude(JsonInclude.Include.NON_NULL) private String addedBy; @JsonIgnore private Date updatedOn; @JsonInclude(JsonInclude.Include.NON_NULL) private String status; @JsonInclude(JsonInclude.Include.NON_NULL) private String annotation; @JsonInclude(JsonInclude.Include.NON_NULL) private Integer year; @JsonInclude(JsonInclude.Include.NON_NULL) private String country; @JsonInclude(JsonInclude.Include.NON_NULL) private byte[] highlight; @JsonInclude(JsonInclude.Include.NON_NULL) private String commentary; @JsonInclude(JsonInclude.Include.NON_NULL) private Short rating; @JsonInclude(JsonInclude.Include.NON_NULL) private Short seriasVolNum; @JsonInclude(JsonInclude.Include.NON_NULL) private List<String> tags; @JsonInclude(JsonInclude.Include.NON_NULL) private Book seriesId; @JsonInclude(JsonInclude.Include.NON_NULL) private List<ReadersReview> readersReviews; // Setters and getters }
可行技术方案
1. 自定义折叠行的Grid(推荐)
实现思路
基于普通Grid组件,为每行设计主信息+可展开详情区的结构:
- 主行展示核心信息:书名、作者、年份、评分等
- 点击主行展开下方多行区域,展示注释、标签、读者评论等详情
- 评论区再做二级折叠:默认展示评论内容,点击编辑按钮展开评论编辑表单
关键细节
- 用虚拟滚动优化大数据量渲染:只渲染可视区域内的行,避免DOM节点过多导致卡顿
- 为每行维护展开/折叠状态,通过前端状态管理控制详情区的显示/隐藏
- 评论编辑逻辑:点击评论项的编辑按钮,切换到编辑模式,提交后调用后端接口更新数据,同时刷新对应评论项
优势
- 兼容大数据量场景,性能可控
- 完全自定义展示结构,适配复杂字段的分层需求
- 编辑逻辑易实现,无需依赖特殊组件
2. Accordion分组+内嵌Grid/列表
实现思路
结合Accordion的分组折叠能力与Grid的列表展示:
- 按年份(或其他维度)用Accordion做一级分组,每个面板对应一个年份区间的图书
- 每个Accordion面板内嵌入Grid展示该年份的图书主信息,图书行同样支持展开详情与评论区
关键细节
- 前端或后端按年份预分组数据,减少前端渲染压力
- 内嵌Grid同样启用虚拟滚动,处理单年份下的大量图书
- 评论编辑逻辑同方案1,在展开的详情区内实现
优势
- 天然契合“按年份排序”的需求,层级清晰
- Accordion的折叠/展开能力无需自行开发,降低实现成本
3. 适配TreeGrid的方案
实现思路
虽然TreeGrid要求节点为同一类型,但可通过包装统一节点类绕过限制:
- 创建通用TreeNode类,包含节点类型(BOOK/REVIEW)、关联数据(Book或ReadersReview)、父节点ID等字段
- 将Book对象转换为父节点,其下的每个ReadersReview转换为子节点
- 配置TreeGrid的列渲染规则,根据节点类型展示对应内容(图书信息或评论内容),评论节点添加编辑/删除按钮
关键细节
- 前端负责数据转换,将Book列表转为TreeGrid可识别的树形结构
- 配置TreeGrid的展开/折叠逻辑,默认展开图书节点,评论节点可单独折叠
- 编辑评论时,直接在TreeGrid的评论节点行内渲染编辑表单,提交后更新节点数据
优势
- TreeGrid自带成熟的折叠/展开、层级管理能力,无需自行实现状态逻辑
- 适合有明确层级关系的内容展示
通用注意事项
- 所有方案必须启用虚拟滚动,处理数千条数据的性能问题
- 编辑操作需做权限校验:仅允许评论作者编辑/删除自己的评论,前端可先做校验,后端再做二次验证
- 数据更新后采用局部刷新,避免重新渲染整个列表,提升用户体验
内容的提问来源于stack exchange,提问作者Gary Greenberg
相关产品推荐
相关产品推荐

