FORGE KUI / learn

构建大数据列表工作台

理解数据模型、可见行、选择、跳转和详情联动。

版本 3.61.7

第08课
准备
完成布局与事件课程
学完可以做
可滚动和跳转的一万条数据工作台
下载工程 ↓workbench.zip

运行和文件分工

解压工作台工程,按下列命令构建。workbench.html 提供区域和样式;main.cpp 提供合成数据、VirtualList 与事件。侧栏栏目用于展示布局,文件数据不来自磁盘。

powershell
$cxxStandard = Read-Host SDK-standard
cmake -S . -B build -A x64 "-DCMAKE_CXX_STANDARD=$cxxStandard" -DKui_DIR=C:/SDK/kui-cpp/cmake
cmake --build build --config Release --parallel 4
.\build\Release\forge_workbench.exe

数据总量与实际行数

totalItems 是数据总数,itemHeight 是固定行高,overscan 为可视区域外预留行。renderItem 按索引创建一行;滚动时不需要把一万条数据全部放进 DOM。

cpp
    kui::VirtualListConfig rows;
    rows.totalItems = 10000;
    rows.itemHeight = 54;
    rows.overscan = 3;
    rows.renderItem = [&](kui::Document* document, kui::u32 index) {
        const char* names[] = {"workspace-shell", "component-tokens", "asset-inspector", "project-overview", "navigation-rail", "activity-stream"};
        const std::string name = std::string(names[index % 6]) + (index < 6 ? "" : "-" + std::to_string(index + 1)) + ".html";
        auto row = document->createElement("div");
        row->setAttribute("class", index == selectedIndex ? "row selected" : "row");
        row->setAttribute("data-index", std::to_string(index));
        row->setInnerHTML("<span class='file-icon'>HTML</span><span class='file-name'>" + name + "<span class='file-sub'>Desktop studio / Interface</span></span><span class='file-kind'>HTML</span><span class='status'>Ready</span><span class='file-size'>" + std::to_string(12 + index % 80) + " KB</span>");
        row->addEventListener("click", [&, name, index](kui::Event&) { select(index, name); });
        return row;
    };
    list.setup(container, rows);

选择状态放在模型里

selectedIndex 在宿主中保留;renderItem 根据它恢复 selected class。因为行会离开可见区,不能只给当前 DOM 加 class 而不记录选择。

cpp
    kui::u32 selectedIndex = 0;
    auto select = [&](kui::u32 index, const std::string& name) {
        selectedIndex = index;
        auto visible = doc->querySelectorAll(".row");
        for (const auto& node : *visible) {
            auto* element = dynamic_cast<kui::Element*>(node.get());
            if (!element) continue;
            element->removeClass("selected");
            if (element->getAttribute("data-index") == std::to_string(index)) element->addClass("selected");
        }
        doc->getElementById("selected")->setTextContent(name);
        doc->getElementById("event-status")->setTextContent("Selected: " + name);
    };

观察虚拟化是否生效

先看实际行为,再调数据量。

  1. 滚动到底部,再回到顶部,检查行号和详情内容。
  2. 点击跳转第 5,000 项,确认可见区域变化。
  3. 比较页面显示的实际渲染行数与一万条总量;它不是性能跑分。
  4. 选择一行,滚出视口后再返回,确认样式与详情保持一致。

练习:改变数据与行高

先改变 totalItems,再单独改变 itemHeight 并同步行 CSS。每次构建后检查跳转、滚动范围和选中项;数据缩短时把超出范围的选择归位。

  • 数据量变化后,页面不能出现空洞或越界索引。
  • 最小窗口仍能滚动到最后一项。
  • 更高的行高应减少可见行数,而不是让文本互相覆盖。

文档有误或遗漏?

反馈此页问题 →