LoginSignup
70
54

More than 3 years have passed since last update.

仮想DOMってすげーんだぜ!

Last updated at Posted at 2019-12-12

この記事は福岡若手Sier_bc Advent Calendar 2019の11日目の記事です。

はじめに

今回は仮想DOMについて書いてみました。

  • フロントエンドに興味のある方
  • 仮想DOMについて知りたい方

を対象にしています。

そもそもDOMって何よ?

「Document Object Model」の略ですが、Wikipedia先生の説明では

DOMは、HTML文書やXML文書(あるいはより単純なマークアップされた文章など)をオブジェクトの木構造モデルで表現することで、ドキュメントをプログラムから操作・利用することを可能にする仕組みである。Documentの種類、操作に用いるプログラミング言語の種類に依存しない仕様である。

要するに、
HTMLを構築する木構造データのことだよ!プログラミング言語で操作できるよ!
ってことです。ここで注意しなければならないのは、MDNの説明にも

(前略)ふつうは JavaScript を使用しますが、 HTML、 SVG、 XML などの文書をオブジェクトとしてモデリングすることは JavaScript 言語の一部ではありません。

とあるように、
DOMはJavascriptを用いて操作することができるけど、Javascriptの一部じゃない
ってことです。さらに、WebブラウザはDOMからHTMLを解析してWebページをレンダリングします。

本記事では仮想DOMと区別して、通常のDOMをリアルDOMと呼称します。

じゃあ仮想DOMって何よ

正体はJavascriptのオブジェクトです。
JavascriptのオブジェクトでリアルDOMを仮想的に作って、

  1. 仮想DOMを二つ用意
  2. 一方の仮想DOMをJavascriptで操作(一般的にリアルDOMを操作するより速い)
  3. 変更前後の仮想DOMの差分を比較
  4. 差分だけをリアルDOMに反映
  5. 反映されたリアルDOMをブラウザがレンダリング

ということで最終的にリアルDOMを操作するのですが、通常、リアルDOMを操作する場合はリアルDOMが変更されるたびにブラウザがHTMLを解析してレンダリングするのでコストが高いです。

仮想DOMを使うメリットはレンダリングコストを低くできることの他に、

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

です。

じゃあどう変わるのか見てみようじゃないの

  • リアルDOMを操作する場合
  • 仮想DOMをVue.jsを使って操作する場合

を見てみましょう。

リアルDOMを操作する場合

こちらを参考にさせていただきました。

<div id="app">
  <p id="counter">0</p>
  <button type="button" id="increment">+1</button>    
</div>

<script>
const state = { count: 0 };
const btn = document.getElementById('increment');
btn.addEventListener('click', () => {
  const counter = document.getElementById('counter');
  counter.innerText = ++state.count;
})
</script>

リンク先にもありますが、このコードを見ると

  1. stateというオブジェクトで現在のcountを管理しよう
  2. ボタンをクリックしたらインクリメント処理を行おう
  3. state.countをインクリメントしよう
  4. state.countを表示するために表示する要素(p#counter)を取得しよう
  5. 取得した要素の文字をstate.countで更新しよう

と考えると思います。まぁこれでもいいんですけど、

  • いちいち要素をJavascriptで取得してるからUIとロジックが混在
  • HTMLにもJavascriptにも状態の初期値が記載
  • UIとロジックを結びつけるためにわざわざリスナーを定義してる

っていうのがめんどくさいですね。

仮想DOMをVue.jsを使って操作する場合

こんな感じのコードになるかと思います。

<template>
  <div>
    <p>{{ count }}</p>
    <button v-on:click="increment">+1</button>
  </div>
</template>

<script>
new Vue({
  data: {
    count: 0
  },
  methods: {
    increment: function() {
      this.count += 1
    }
  }
})
</script>

ね?

  • JavascriptでHTMLの要素を取得しないからUIとロジックが分離
  • 状態の初期値はJavascript側で完結
  • リスナー代わりのv-onディレクティブがHTML側に記載されてるからUIとロジックを繋ぐ処理が簡略化

されているでしょう。これが仮想DOMを使うメリットです。

あれ?結果的にレンダリングコストは変わるん?

一応色々とベンチマークはあるようなのですが、フレームワークによって得意不得意がある模様です。

まとめ

以上で、仮想DOMの説明をしてみました。仮想DOMは確かにレンダリングコストを低減する画期的なものですが、やはり開発する上ではUIとロジックが分離されるという点も非常に強力で、生産性向上に寄与するものだと思います。

謝辞

今回の記事について、様々な記事にお世話になりました。
この場をお借りしてお礼申し上げます。

70
54
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
54