【Vue.js】仮想DOMについてまとめてみた


はじめに

Vue.jsを学習していく中で「仮想DOM」という概念を知りました。
そもそも仮想DOMとは何なのか、どんなメリットがあるのか調べたのでまとめてみました。

そもそもDOMって何?

DOMとはDocument Object Modelの略で、HTMLやXML文書を操作するためのAPI(インターフェイス)です。
ウェブページとJavaScriptなどのスクリプト言語を繋ぐ橋渡し的な存在です。

仮想DOMと区別するためにリアルDOMと呼ぶこともあります。

DOMツリーって何?

DOMのモデルは文書をツリー構造で表現します。
<html>タグから枝分かれしていき、<head>,<body>タグ、その中身のタグや要素に分かれていきます。

このDOMツリーの<html>,<body>といった一つ一つの要素をオブジェクトとして扱い、これらをNode(ノード)と呼びます。

仮想DOMの発想の原点

ウェーブページの内容はDOMに格納されていて、内容を変更したいときにJavaScriptなどの言語を介して操作することができます。
DOM操作の処理フローは以下のようになっています。

  1. DOMツリーを再構築する
  2. DOMツリーとCSSOMツリー※を組み合わせてレンダリングツリーを構築する
  3. レンダリングツリーでレイアウトを行い、各ノードの位置やスタイルを計算する
  4. レイアウト結果をもとに描画する

※ CSSOM: CSS Object Modelの略で、CSS版DOMのようなものです。

レンダリングはブラウザにとってコストの高い処理となるため、できるだけ避けたいフローです。無駄なレンダリングをなくし、効率の良い処理をするためにはどうすれば良いでしょうか。

変更があった部分のみレンダリングする

これが実現できれば無駄なレンダリングは起きませんよね。
そこで考えられたのが、仮想DOMという概念です。

仮想DOMって何?

簡単にいうと、リアルDOMを模したJavaScriptのオブジェクトです。

  1. 仮想DOMを2種類用意する
  2. 一方の仮想DOMをJavascriptで操作
  3. 変更前後の仮想DOMの差分を比較
  4. 差分だけをリアルDOMに反映

上記のようなフローでリアルDOMを操作します。
仮想DOMを用いることで、無駄なレンダリングを避ける以外に

  • ロジックとUIが分離できる
  • 状態の管理を簡単にできる
  • ロジックとUIを繋ぐ処理を簡単にできる

といったメリットがあります。

リアルDOMと仮想DOMを比べてみよう

ここからは実際にリアルDOMと仮想DOMの処理の違いを見ていきたいと思います。

  • 素のJavaScript(リアルDOM)を使う場合
  • Vue.js(仮想DOM)を使う場合

今回は簡単なカウントアップ処理で2つを比べていきます。

リアルDOM(JavaScript)

index.html
<div id="app">
  <button class="count_up">count up</button>
  <p class="count_num">0</p>
</div>
app.js
const countButton = document.querySelector('.count_up');
const state = { count: 0 };

countButton.addEventListener('click', () => {
    const countContent = document.querySelector('.count_num');
    countContent.innerHTML = ++state.count;
});

上記のようなリアルDOMの操作は

  • ボタンをクリックするとp.count_numが書き変わるというUIと、カウントをインクリメントするというロジックが混同している
  • UIとロジックを繋ぐaddEventListenerを使っている。(より複雑になるとaddEventListenerが増えがち)

などのデメリットがあります。

仮想DOM(Vue.js)

index.html
<div id="app">
   <button @click="countUp">count up</button>
   <p>{{ count }}</p>
</div>
app.js
new Vue({
    el: "#app",
    data: {
        count: 0,
    },
    methods: {
        countUp: function() {
            this.count += 1;
        }
    }
})

リアルDOMの操作に比べると

  • UIとロジックが分離できる
  • @clickを使うことでUIとロジックを繋ぐ処理が簡単になった
  • 状態の一元管理ができる

といったメリットがあります。

まとめ

仮想DOMはレンダリングコストの削減だけでなく、UI/ロジックの分離や状態管理の簡略化など、開発の効率を上げる上で必須の概念であると理解しました。

参考文献