はじめに

Vue.jsとは、バニラJSでは複雑な実装を必要としたユーザーインターフェースを、簡単に、かつ効率的に開発することができるJavascriptのフレームワークです。
この記事ではVue.jsを含むフロントエンドフレームワークの特徴を紹介し、純粋なJavascript, バニラJSでの実装と比べどういったメリットが生まれるのかを紹介します。

コンポーネントとは

ある画面を作成する際、1つのファイル内でコードを完結させるのではなく、コンポーネント(ファイル)として分割しそれらを組み合わせて実装していきます。
これはファイルの肥大化を防ぎ、メンテナンス性を高める目的があります。また、ボタンやテキストボックスなど、複数画面で登場する要素をコンポーネント化しておくことで、各画面で重複して作成する必要が無くなります。
Javascriptのフレームワーク全般に当てはまる設計方法です。

コンポーネントとは

リアクティブな開発とは

ReactやVueでの開発において「リアクティブ」な値の仕組みを理解することが重要です。そもそもここでいうリアクティブとは、内部のデータと画面上の描画がリアルタイムで同期しているようなイメージです。データが更新されれば描画も同じく更新され、また画面上で文字の入力やボタン操作を行うとデータにその値が反映されます。従来のバニラJSではデータの更新とそれに紐づく描画部分を、手動で同期させる必要がありました。

コードを用いて両者の実装手順の違いを説明します。
下の画像のような、CLICKボタンを押すとcountの数値が1ずつ増えていくアプリケーションを作成するとします。

Javascript

バニラJSでは、DOMと呼ばれる、webページを構成する要素群を直接操作します。

<body>
  <div>
    <div id="countDisplay" class="mb-2 font-bold">
      count: 0
    </div>
    <button id="incrementButton" class="button">
      CLICK
    </button>
  </div>

  <script>
    // 初期化
    let count = 0;

    // DOM要素の取得
    const countDisplay = document.getElementById('countDisplay');
    const incrementButton = document.getElementById('incrementButton');

    // ボタンのクリックイベントハンドラー
    const onClickPlus = () => {
      count ++; // カウントを増加
      countDisplay.textContent = `count:${count}`; // 表示を更新
    };

    // ボタンにクリックイベントリスナーを追加
    incrementButton.addEventListener('click', onClickPlus);
  </script>
</body>

CLICKボタンが押下されるとイベントが呼び出されます。

incrementButton.addEventListener('click', onClickPlus);

イベント処理では変数countの値を更新し、表示させる為の数値をDOM要素(HTMLタグ)ごと作成します。

const onClickPlus = () => {
  count++; // カウントを増加
  countDisplay.textContent = `count: ${count}`; // 表示を更新
};

そしてDOM要素ごと置き換えることで描画を更新します。
バニラJSでは、DOM要素の位置を特定する為のid値、JS側でのDOM要素の取得、DOM要素に対しイベントが発生したかを検知するリスナー、と簡単な動作を実行するのにも、複数の手順が必要です。

Vue.js

一方でReactやVueなどのフレームワークでは、いきなりDOMを操作する前に、仮想DOMと呼ばれるものをJS側で作成します。そこでは変更前との差分を抽出し、その後DOMに差分のみを反映させます。必要な変更箇所のみDOM操作することで、処理効率が上がるだけでなく、コードも簡略化させることが出来ます。

<template>
  <div>
    <div class="mb-2 font-bold">
      {{ `count:${count}` }}
    </div>
    <button 
      class="p-2 border border-red-500 text-red-500"
      @click="onClickPlus()"
    >
      CLICK
    </button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  name: 'App',
  setup() {
    // 初期化
    const count = ref(0);
    
    // ボタンのクリックイベントハンドラー
    const onClickPlus = () => {
      count.value ++;
    };
    
    return {
      count,
      onClickPlus
    };
  },
});
</script>

Vueでは次のように手順を踏みます。
始めに画面上で表示する変数count をref関数で定義します。

const count = ref(0);

値に対する操作が常に追跡される状態となり、変更を検知すると即座に反応してデータを同期・DOMの編集などを自動で行ってくれます。これがリアクティブな値です。

次にbutton タグに直接イベントハンドラを指定します。

<button @click="onClickPlus()">

イベント処理では変数countの値を更新します。ref関数の値はvalue オブジェクトに格納されている為.value を更新します。

const onClickPlus = () => {
  count.value ++;
};

このようにVueでは、リアクティブなデータの定義とイベントハンドラの定義を書き、DOM要素に直接それらを組み込むことで視覚的にも理解しやすい実装を実現できます。

おわりに

今回紹介した内容は、VueだけでなくReactなど他のフレームワークでも通用する部分であり、フロントエンド開発全般で重要な考えや仕組みです。公式ドキュメント(Vue.js)の資料も豊富なので取り掛かり易い点も魅力です。
この記事が少しでも参考になれば幸いです。