运行和文件分工
解压工作台工程,按下列命令构建。workbench.html 提供区域和样式;main.cpp 提供合成数据、VirtualList 与事件。侧栏栏目用于展示布局,文件数据不来自磁盘。
$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。
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 而不记录选择。
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);
};
观察虚拟化是否生效
先看实际行为,再调数据量。
- 滚动到底部,再回到顶部,检查行号和详情内容。
- 点击跳转第 5,000 项,确认可见区域变化。
- 比较页面显示的实际渲染行数与一万条总量;它不是性能跑分。
- 选择一行,滚出视口后再返回,确认样式与详情保持一致。
练习:改变数据与行高
先改变 totalItems,再单独改变 itemHeight 并同步行 CSS。每次构建后检查跳转、滚动范围和选中项;数据缩短时把超出范围的选择归位。
- 数据量变化后,页面不能出现空洞或越界索引。
- 最小窗口仍能滚动到最后一项。
- 更高的行高应减少可见行数,而不是让文本互相覆盖。
文档有误或遗漏?
反馈此页问题 →