Virtual DOM — 違う部分だけを実DOMに当てる
画面を書き換えるとき、毎回HTML全体を作り直したら遅くなります。実DOM(ブラウザが描画する本物の要素)の操作はとても重いからです。かといって「どこが変わったか」を手作業で追うのは大変。
そこで React などは、軽量なJavaScriptのコピー=仮想DOM(Virtual DOM)を持ちます。変更があると「前回の仮想DOM」と「今回の仮想DOM」を比べ(diff)、違う部分だけを実DOMに当てます(patch)。下の図1でリストを編集して、何が「使い回され」何が「作り直される」かを見てください。
なぜ「差分だけ」が速いのか
仮想DOMはただのJSオブジェクトなので、作るのも比べるのも軽い。重いのは実DOMへの反映だけです。だから「新旧の仮想DOMをメモリ上で比較し、本当に変わった最小限を実DOMに書き込む」という二段構えにすると、画面の一部だけ変えたいときに全体を作り直さずに済みます。図1で「2番目を変更」を押すと、ほかのカードは維持(0操作)のまま、1枚だけ更新されるのが分かります。
ここで効くのが key です。各カードに安定した key を付けておくと、差分計算は「同じ key =同じもの」と見なせます。だから「1・2番目を入替」のように順番が変わっても、作り直さずに移動として扱えます。逆に key が無い/不安定だと、別物と誤判定して余計な作り直しが起き、入力中のフォームが消えるなどの不具合にもつながります。リスト描画で key が大切なのは、この差分計算を助けるためなのです。
- 仮想DOM
- 実DOMの構造を写した軽量なJSオブジェクトのツリー。作成・比較が安い。
- diff(差分検知)
- 前回と今回の仮想DOMを突き合わせ、どこが変わったかを割り出す処理。
- patch(パッチ)
- diffで見つかった差分だけを実DOMに当てること。重い操作を最小化する。
- key
- リスト各要素の安定した目印。同一判定を助け、無駄な作り直しを防ぐ。
まとめ
Virtual DOM は、「軽いコピー同士を比べて、違う部分だけ本物に当てる」という発想で、重い実DOM操作を減らす仕組みです。図1で見たように、維持できるものは使い回し、key があれば移動も作り直しません。画面更新のたびに全部を描き直しているわけではない——この差分の最小化が、サクサク動くUIの裏側にあります。