Vue.jsはJavaScriptのデータとHTMLテンプレートのDOM要素を結びつける「リアクティブなデータバインディング」を備えています。
リアクティブなデータバインディングとは、HTMLテンプレート内で対象となるDOM要素にバインディングを指定することで、Vue.jsがそのデータの変更を検出する度に、バインディングされているDOMが自動で表示内容を更新することです。
リアクティブシステム
Vue.jsのアプリケーションではデータが変化すると、変化した内容が即座にDOMに反映されます。Vue.jsが持つこの仕組みを「リアクティブシステム」と呼びます。また、リアクティブシステムの監視下に置かれているデータのことを「リアクティブデータ」と呼びます。
リアクティブシステムの例
リアクティブシステムの例として身近でわかりやすいものを上げると、Excelのスプレッドシートがあるかと思います。
Excelのシートに数値を入力しておき、それをもとに計算する関数を指定しておくと、計算結果が自動で表示されます。
例えば
A1のセルに数値「1」を入力します。
A2のセルに数値「2」を入力します。
A3のセルに関数「=SUM(A1:A2)」を入力します。
A3のセルは、関数を入力した時点で「3」と表示されます。
ここでA1のセルの値を「3」に更新します。
すると、A3のセルの値が自動的に「5」に更新されます。
データ(ここではA1、A2のセルに入力した値)とDOM(ここではA3のセル)が関連付けられてリアクティブ(反応的)に動作するします。これがリアクティブシステムの簡単な例としてVue.jsの公式サイトのページでも紹介されています。
リアクティブシステムを持たない状態のJavaScriptでは、上記の動作を実現するために多くのコード(処理)を書く必要があります。
- セルA1とA2の計算結果を取得する処理を用意しておく。
- セルA1が変更された時のイベントを定義しておく。
- セルA2が変更された時のイベントを定義しておく。
- イベント内でセルA1の値を取得する。
- イベント内でセルA2の値を取得する。
- イベント内でセルA1とA2の計算結果(加算結果)を取得する。
- イベント内でセルA3(計算結果を表示する場所)を取得する。
- イベント内でセルA3に計算結果を表示する。
上記の動作をリアクティブシステムを持つVue.jsで実現すれば、以下のコード(処理)で済みます。
- セルA1とセルA2の計算結果を取得する処理を用意しておく。
- セルA1のデータを定義して紐づけておく。
- セルA2のデータを定義して紐づけておく。
- セルA1とセルA2の計算結果のデータを定義してセルA3に紐づけておく。
リアクティブシステムを確認する簡単なプログラム
ここではリアクティブシステムを確認できる簡単なプログラムのソースコードを記載しておきます。
1 2 3 |
<div id="app"> <span>現在の日時: {{currentDateTime.toLocaleString()}}</span> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Vue.createApp({ data: function() { return { currentDateTime: new Date() } }, created: function() { let self = this; this.timer = setInterval(function() { self.currentDateTime = new Date(); }, 1000); }, beforeUnmount: function() { clearInterval(this.timer); } }).mount('#app') |
HTMLファイル(拡張子が.htmlのファイル)を作成して、上記のコードを両方とも貼り付けて実行(ファイルを開く)と、1秒(1000ミリ秒)ごとに画面に表示された現在の日時が更新されることが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<script src="https://unpkg.com/vue@next"></script> <div id="app"> <span>現在の日時: {{currentDateTime.toLocaleString()}}</span> </div> <script> Vue.createApp({ data: function() { return { currentDateTime: new Date() } }, created: function() { let self = this; this.timer = setInterval(function() { self.currentDateTime = new Date(); }, 1000); }, beforeUnmount: function() { clearInterval(this.timer); } }).mount('#app') </script> |
データバインディング
JavaScriptのデータをDOM(HTMLテンプレート内の対象の要素)と結び付けることを「データバインディング」といいます。
データバインディングされている状態でJavaScriptのデータを更新すると、HTMLのDOM要素に表示されるデータも自動で更新されます。
Vue.jsで使用されるHTMLベースのテンプレート構文では、このデータバインディングがサポートされています。
Vue.jsの内部では、Vueがテンプレート(HTML)が Virtual DOM(仮想DOM)の描画関数にコンパイルされます。
リアクティブシステムと組み合わせて、Vueは再描画に必要なDOMを把握し、アプリケーションの状態が変更された際に必要最低限のDOM操作のみを行ってくれます。
データバインディングには、JavaScriptのオブジェクトからDOM要素へ一方通行でデータをバインドする「一方向バインディング」と、JavaScriptのオブジェクトとDOM要素がお互いのデータをやり取りする「双方向バインディング」があります。
一方向バインディング
JavaScript上のデータをWebページ(DOM)に自動で反映(表示)する際に利用します。
プログラムのデータが自動でWebページに反映されるので
- 値を算出
- 算出した値を設定
という処理(コード)が必要なくなります。
これにより、スマートにアプリケーションを実装とDOM操作が実現できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<script src="https://unpkg.com/vue@next"></script> <div id="app"> <p>JavaScriptのデータ: {{message}}</p> </div> <script> Vue.createApp({ data: function() { return { message: 'Hello Vue.js!' } } }).mount('#app') </script> |
双方向バインディング
JavaScript上のデータをWebページに反映するだけではなく、ユーザーが入力した値をWebページから取得するしたり、データを同期させたりしたい場合があります。
双方向バインディングを利用すれば、JavaScriptのデータを変更するたびにDOM要素の表示内容を更新し、ユーザーからの入力(input要素での入力など)を検出するたびにJavaScriptのデータを更新ということができます。
双方向バインディングで関連付けられたJavaScriptのデータとDOMの要素データは、相互にやり取りが行われるので同期し続けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<script src="https://unpkg.com/vue@next"></script> <div id="app"> <input v-model="message" /> <p>input要素の値: {{message}}</p> </div> <script> Vue.createApp({ data: function() { return { message: '' } } }).mount('#app') </script> |