Vaadin Grid中使用多个Template渲染同父类不同子类对象问题咨询
问题根因
你当前的写法误用了Grid的addColumn重载方法:
你传入的lambda表达式属于ValueProvider类型,这个重载的作用是把返回值转为字符串直接展示,你返回TemplateRenderer对象自然只会输出对象的toString结果,不会触发模板渲染。addColumn接受Renderer的重载要求你直接传入固定的Renderer实例,不支持按行动态返回不同的Renderer。
方案1:统一模板+dom-if判断(推荐,性能最优)
你之前用dom-if出现两个模板同时展示的问题,是因为没有正确设置判断条件和restamp属性,正确写法如下:
首先定义统一的模板:
public static TemplateRenderer<AbstractPcPart> getUnifiedTemplate() { return TemplateRenderer.of(""" <template is="dom-if" if="[[item.isMemory]]" restamp> <memory-card memory-card='[[item.partCard]]'></memory-card> </template> <template is="dom-if" if="[[item.isGraphicsCard]]" restamp> <graphics-card-card graphics-card='[[item.partCard]]'></graphics-card-card> </template> """) .withProperty("isMemory", part -> part instanceof Memory) .withProperty("isGraphicsCard", part -> part instanceof GraphicsCard) .withProperty("partCard", CardFactory::create); }
然后Grid初始化的时候直接传入这个统一模板即可:
public PcPartsGrid() { super(); addColumn(getUnifiedTemplate()); }
restamp属性会保证条件切换时旧的组件被销毁,不会同时出现两个组件。
方案2:ComponentRenderer实现(写法最简单)
如果你对性能要求不是极致高(单页数据量小于100条的场景几乎感知不到差异),用ComponentRenderer逻辑更直观,不需要写前端模板判断:
public PcPartsGrid() { super(); addColumn(new ComponentRenderer<>(pcPart -> { if (pcPart instanceof Memory) { return new MemoryCardComponent((Memory) pcPart); } else if (pcPart instanceof GraphicsCard) { return new GraphicsCardComponent((GraphicsCard) pcPart); } return new Span("未知配件"); })); }
你只需要把之前的前端模板封装成对应的Vaadin组件即可,代码逻辑全在Java侧控制,不容易出错。
方案3:自定义渲染器(适合复杂场景)
如果确实需要完全动态的模板渲染,可以自己实现Renderer<AbstractPcPart>接口,在render方法里根据当前行数据的类型选择不同的渲染逻辑,不过实现复杂度较高,一般前两个方案就能覆盖绝大多数场景。
内容的提问来源于stack exchange,提问作者Dario Viva
相关产品推荐
相关产品推荐

