一万行の一覧

一万件の受注を並べる画面です。実際に DOM に入っているのは、そのときに見えている二十数行だけです。

スクロール位置から、描く行を決める

枠がどこまでスクロールされたかは、イベントで届きます。窓化そのものは言語の機能ではなく、この画面の書き方です。

me listen: '#box' on: #scroll sendEvent: #scrolled:.

Screen >> scrolled: e = self with: { top: e scrollTop. viewH: e height }.

行の高さは CSS が決めた定数なので、プログラムはそれを知っています。割れば、何行目から何行が要るかが出ます。

Screen >> firstDrawn = ((top // Screen rowHeight) - 2) max: 0.

前後に二行の余裕を足しているのは、速く動かしたときに端が欠けないようにするためです。

詰め物でスクロールバーを正しくする

描かない分の高さは、上下の詰め物の行が持ちます。中身のない行に高さだけを持たせるので、スクロールバーの長さは一万行ぶんになります。

高さ 0 の詰め物は出しません。tbody tr に高さを与えている表では、高さ 0 の tr が消えずに一行分の空きとして残るからです。

速さ

一描画は、一覧が何行あっても変わりません。描くのは常に見えている行だけだからです。

一描画
1,000行を全部描く20.8 ms
10,000行を窓化4.9 ms

ここはブラウザでしか確かめられない

詰め物の高さ、見出しが sticky で占める高さ、端で半分だけ見えている行の扱い。どれもレイアウトが決めるので、作り物の DOM に対する検査では何も言えません。

そこで本物のブラウザを画面なしで動かし、スクロールさせてから「その位置に実際に描かれている行」をブラウザに答えさせています。行の高さを 2px ずらすと、SO-10179 のはずの位置に SO-10167 が来て検査が落ちます。