{
  "lead": "在浏览器里流畅浏览 10 万行以上的表格数据：排序、全文搜索、滚动都不卡顿。数据的生成、存储、排序、过滤全部在 WASM 中完成，页面上始终只有约 40 行 DOM 元素。",
  "formulas": [
    [
      "首个可见行 = ⌊scrollTop / 37⌋",
      "只渲染其后 40 行"
    ]
  ],
  "terms": [
    [
      "数据常驻 WASM 内存",
      "所有行保存在 Rust 的全局状态 <code>static STORE: Mutex&lt;Option&lt;Store&gt;&gt;</code> 中。JS 不持有完整数据，只按需取一小段。"
    ],
    [
      "索引排序",
      "排序和过滤不移动行数据本身，只重排一个下标数组 <code>order: Vec&lt;usize&gt;</code>，交换的是 8 字节的整数，而不是整行字符串。"
    ],
    [
      "全文过滤",
      "把查询词转成小写，逐行检查姓名、邮箱、城市、部门、电话、年龄、薪资是否包含该词，结果写回 <code>order</code>。空查询时恢复全部行。"
    ],
    [
      "虚拟滚动",
      "用一个高度为 <code>总行数 × 37px</code> 的占位元素撑出滚动条。滚动时根据 <code>scrollTop / 37</code> 算出第一条可见行，只渲染这之后的 40 行，并用绝对定位把它们放到正确的位置。"
    ]
  ],
  "flow": [
    [
      "rust",
      "<code>generate_rows(n)</code>：Rust 生成 n 行示例数据并保存在 WASM 内存中。"
    ],
    [
      "rust",
      "<code>sort_by_column(列, 升序)</code> 和 <code>filter_rows(关键词)</code>：Rust 更新下标数组，返回结果行数。"
    ],
    [
      "js",
      "JS 在滚动时调用 <code>get_page(起始行, 40)</code>，Rust 把这一小段数据拼成 JSON 字符串返回。"
    ],
    [
      "js",
      "JS 解析 JSON，生成这 40 行的 HTML，写入 <code>&lt;tbody&gt;</code>。"
    ]
  ],
  "perf": [
    "每次跨越 JS 与 WASM 边界的只有可见的几十行数据，与总行数无关，所以 25 万行和 1 万行滚动起来一样流畅。",
    "搜索框做了 150ms 防抖：连续输入时只在停顿后执行一次过滤。",
    "项目没有引入 <code>serde</code>，JSON 由 <code>get_page()</code> 手工拼接，WASM 体积因此更小。",
    "中文按 Unicode 码点排序，不是按拼音顺序。"
  ],
  "src": [
    [
      "crates/algorithms/data-table/src/lib.rs",
      ""
    ],
    [
      "www/data-table/index.js",
      ""
    ]
  ]
}
