← Angular コース
76. TView と LView — 設計図と台帳
実行時のAngular(Ivyランタイム)は、表示中のコンポーネントごとに2種類のデータを持っています。1つ目のTViewは「テンプレートの設計図」です。0番スロットは h1 要素、1番はテキストノード、というテンプレートの構造情報を持ち、同じコンポーネントを画面に100個表示してもTViewは1つだけで全インスタンスが共有します。作られるのは最初の1個目が表示されるときの一度きりで、これをファーストパスと呼びます。
2つ目のLViewは「インスタンスごとの台帳」で、実体はただの配列です。設計図の番号に対応するスロットに、実際のDOMノードへの参照・コンポーネントのインスタンス・各バインディングの前回値が入っています。更新モードの命令がやっているのは「スロットn番の前回値と今回の値を比べ、違ったときだけ対応するDOMノードを書き換え、台帳の値を更新する」という突き合わせ作業です。画面更新の正体は、この台帳との差分チェックであり、DOMツリーの再構築ではありません。
構造(全インスタンス共通)と状態(インスタンス個別)を2枚に分けるのは効率のためです。一覧画面で行コンポーネントを1000個並べても、設計図は1つでメモリは台帳の分しか増えず、更新は各台帳の前回値比較だけで済みます。デバッグのセクションで使ったAngular DevToolsのコンポーネントツリーは、実はこのLViewが親子につながったツリーを覗いていたのだ、と理解できます。
サンプルコード(フレームワーク環境が必要なため表示のみ)
// template: '<h1>{{ title() }}</h1><p>{{ count() }}</p>' の場合
//
// ── TView(設計図・全インスタンス共有・1つだけ)──
// スロット0: h1 要素がある
// スロット1: テキストノード(title のバインディング)
// スロット2: p 要素がある
// スロット3: テキストノード(count のバインディング)
//
// ── LView(台帳・インスタンスごと)──
// インスタンスA: [<h1>実DOM参照, '売上', <p>実DOM参照, 3, ...]
// インスタンスB: [<h1>実DOM参照, '在庫', <p>実DOM参照, 7, ...]
//
// ── 更新モードの仕事 ──
// title() の今の値と台帳の前回値を比較
// 同じ → 何もしない(DOMに触らない)
// 違う → そのテキストノードだけ書き換えて台帳を更新
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗