You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin 23中Details组件能否实现懒加载?替代方案咨询

Vaadin Details组件懒加载实现方案

原生Details组件实现懒加载

Vaadin Details默认会预渲染内容,但可以通过监听展开状态变化事件实现懒加载逻辑,不需要替换组件。核心思路是:初始时只渲染标题和占位内容,当用户第一次展开面板时,再异步加载并渲染实际内容。

实现步骤

  • 初始化Details时,设置一个占位内容(比如“加载中...”),或者暂时不设置内容
  • 给Details添加opened-changed事件监听器
  • 在监听器中判断:如果面板处于展开状态,且内容未加载过,则异步获取数据并替换占位内容

Java代码示例

Details details = new Details("用户详情");
// 初始设置占位内容
details.setContent(new Span("加载中..."));

// 监听展开状态变化
details.addOpenedChangeListener(event -> {
    if (event.isOpened()) {
        // 检查内容是否已加载,避免重复请求
        if (!(details.getContent() instanceof UserInfoComponent)) {
            // 异步从后端获取数据
            CompletableFuture.supplyAsync(() -> userService.getUserDetails(123))
                .thenAccept(user -> {
                    // 在UI线程中更新内容
                    UI.getCurrent().access(() -> {
                        UserInfoComponent content = new UserInfoComponent(user);
                        details.setContent(content);
                    });
                });
        }
    }
});

TypeScript代码示例

import { Details, Span } from '@vaadin/details';
import { UserInfo } from './models';

const details = new Details('用户详情');
details.content = new Span('加载中...');

details.addEventListener('opened-changed', (event: CustomEvent) => {
    if (event.detail.value) {
        // 避免重复加载
        if (!(details.content instanceof UserInfoComponent)) {
            fetch('/api/users/123')
                .then(res => res.json())
                .then((user: UserInfo) => {
                    const content = new UserInfoComponent(user);
                    details.content = content;
                });
        }
    }
});

替代方案

如果原生Details的懒加载逻辑无法满足需求,比如需要更灵活的样式控制或复杂的加载状态管理,可以考虑以下替代方案:

1. 使用Accordion组件

Accordion的面板同样支持opened-changed事件监听,逻辑和Details完全一致,适合需要多个折叠面板的场景:

Accordion accordion = new Accordion();
AccordionPanel panel = accordion.add("订单详情", new Span("加载中..."));

panel.addOpenedChangeListener(event -> {
    if (event.isOpened() && !(panel.getContent() instanceof OrderInfoComponent)) {
        // 异步加载订单数据并更新内容
    }
});

2. 自定义折叠面板

用Button配合容器组件(如Div)手动实现折叠逻辑,完全自定义样式和加载流程:

Button toggleBtn = new Button("展开订单详情", new ArrowRightIcon());
Div contentDiv = new Div();
contentDiv.setVisible(false);

toggleBtn.addClickListener(e -> {
    boolean isOpened = contentDiv.isVisible();
    if (isOpened) {
        toggleBtn.setIcon(new ArrowRightIcon());
        contentDiv.setVisible(false);
    } else {
        toggleBtn.setIcon(new ArrowDownIcon());
        // 首次展开时加载内容
        if (contentDiv.getChildren().count() == 0) {
            CompletableFuture.supplyAsync(() -> orderService.getOrderDetails(456))
                .thenAccept(order -> UI.getCurrent().access(() -> {
                    contentDiv.add(new OrderInfoComponent(order));
                }));
        }
        contentDiv.setVisible(true);
    }
});

add(toggleBtn, contentDiv);

内容的提问来源于stack exchange,提问作者alexanoid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 04:37:02