Vue.jsのコンセプト~その1~:プログレッシブフレームワーク
「どんな時でも、どんな規模でも柔軟に使えるべき。」という思想になっています。アプリケーションの段階的な要求変化に応じて問題解決する方法を提供することが可能です。最初は小規模でも必要になった際に適切なライブラリやツールを導入することで大きく対応できるという柔軟さを持ちます。
Vue.jsのコンセプト~その2~:「データ駆動」になっていること。
データメインで考える設計思想になっています。
データバインディング機能、リアクティブシステム
JavaScriptのデータを書き換えるだけで、描画内容(DOM)も書き換わる仕組みのことです。Vue.jsが備えているリアクティブシステムという仕組みによって実現されています。(リアクティブシステムはデザインパターンのオブザーバパターンを元に設計されています。)リアクティブシステムの監視下におかえれたデータのことをリアクティブデータと呼びます。JavaScriptのデータを書き換えるだけで、描画内容も書き換わる仕組みのことで、テンプレートで定義しているデータの内容をHTMLタグ(CSSや、属性等)に紐付けることができます。
リアクティブシステムの実装方法
「算出プロパティ」と「ウォッチャ(Watcher)」の組み合わせによって実現します。
リアクティブシステムの仕組み
後で追加したプロパティはリアクティブにはならない。
下記のように後でVueインスタンスにプロパティを追加することもできます。ただdataに記述していないデータの場合はVueインスタンスを直接覗いてみれば分けると思いますが、セッターとゲッターが付加されていないのでリアクティブデータにはなりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<script src="vue.js"></script> <div id="app2"> <p>{{ message }}</p> <p>{{ name }}</p> <button @click="message='変更'">messageボタン</button><!-- 変更できる。--> <button @click="name='変更'">nameボタン</button> <!-- 変更できない。--> </div> <script> var vm2 = new Vue({ el: "#app2", data: { message: "テスト" } }) vm2.message = "変更します"; vm2.name = "太郎"; </script> <style> .red { color: #ff0000; } .yellow { background-color: #ffff00; } </style> |
基本的には、データをリアクティブデータとして運用する事がVue.jsの基本になるのでdataに記述するようにしましょう。
外から渡すことは可能
ただ、下記のようにVueインスタンス外に定義されているデータをVueインスタンス内に渡してデータ内容として定義する事は可能になります。ややこしいですが、このような仕様になっています。
1 2 3 4 5 6 7 8 |
const txt = "テキスト"; let vm2 = new Vue({ el: "#app2", data: { message: "テスト", text: txt } }) |
データバインディングを行うには?
使用する全てのデータを「リアクティブデータ」として定義する必要があります。
リアクティブデータとは?
Vue.jsによって、データを取得や設定した際に、反応できるデータのことです。
データバインディングを行うには?
テキストのバインディングには、Mustache(マスタッシュ)という記法を使う。
「{{}}」(二重括弧)を使ったMustache(マスタッシュ)という表記法で、テキストデータをバインディングできます。
v-bindを使う。
ディレクティブ「v-bind」を使います。属性や、CSSのバインディングを行うことができます。
修飾子 | 説明 |
.prop | 属性の代わりに、DOMプロパティとしてバインドする。 |
.camel | ケバブケースの属性名をキャメルケースとしてバインドする。 |
.sync | 双方向バインディングを行う。 |
v-modelを使う。
v-modelを使うことで、下記二つの処理を同時に行うことができます。
- データバインディングで、要素のvalueの値を更新する。
- イベントハンドリングで、受け取った値を、データに代入する。
仮想DOM
リアクティブデータに基づいてVueがメモリ上に構築するDOMになります。DOMを象ったJavaScriptのオブジェクトになります。
仮想DOMにより、データ内容の差分だけを差し替えています。これにより、レンダリングスピードを大幅に向上させています。仮想DOMを作るために、「v-if」等の「テンプレート」記法を採用しています。
なぜ仮想DOMを使うのか?
DOMに要素を追加したりするのは実際のブラウザに存在するDOMを操作することになるので非常にコストがかかって遅くなります。部分的にDOMの要素を変更するに当たっても実際のDOMではなく、DOMを象ったJavaScriptのオブジェクトなのでかなり高速にデータ処理をする事が可能になります。
仕組み
「前回まで表示していた仮想DOM」と「今回変更した仮想DOM」をどちらもJavaScriptコード内で保持しておいて差分を比較しています。
$mount('el')
仮想DOMを実際のブラウザのDOMに反映させます。
Vue.jsのコンセプト~その3~:「コンポーネント指向」になっていること。
サイトの規模がおおきくなると、HTML/CSS/JavaScriptコードの管理が乱雑になってしまいます。
Vue.jsでは、機能ごとにCSS、JavaScriptとテンプレートを1つのセットにして、管理しているので、ソースを探しやすいです。
もちろん、ヘッダー、フッター等の共通化するコンポーネントも使うことができます。
Vue.jsのコンセプト~その4~:「MVVMモデル」になっていること。
MVCから派生したMVVM(Model-View-ViewModel)のアーキテクチャになっています。
ViewModel(ビューモデル)
ViewとModel(バインディングデータ)を仲介する役割でMVCで言えばコントローラ的な役割です。ただ、MVCでいうコントローラは描画処理には介入しないですが、ViewModelはデータバインディングを通じてモデルとビューを自動的に結びつけます。
テンプレートとは?
Vue.jsにて、DOMを構築する手段のことです。
テンプレートの構文は、HTMLベースになっているため、エディタとの親和性が高く、エンジニアとデザイナーの共同作業に向いています。
ディレクティブとは?
ディレクティブとは、「v-~」で始まる特別な属性のことで、「テンプレート」と「ロジック」を紐づけることができます。
Vue.jsでは、「ディレクティブ」を使ってテンプレートと連携します。(要は、データバインディングです。)
ディレクティブの種類
ディレクティブ | 説明 |
---|---|
v-for | 繰り返し描画できます。 |
v-on | クリックした際の動作を定義できます。 |
v-model | データとフォームの入力項目をバインドできます。 |
v-if | 条件分岐です。 |
v-text | dataにアクセスします。配下の要素まで置き換わるので注意です。 |
{...} | dataにアクセスします。「v-text」と似ていますが、配下の要素にアクセスはしません。 |
v-pre | {...}を無効化します。 |
v-bind | コンポーネントのデータとHTML要素を同期させます。(バインディング) |
v-html | 画面にそのままhtmlタグを適用して出力させる事ができます。なので、v-textではできない文書内での改行の出力なんかに使われていたりします。 |
key | 単なる文字列を表します。 |
ディレクティブの使い方
構文
1 |
ディレクティブ :引数 修飾子 = 値(JavaScriptの式) |
具体例
1 |
v-bind :atai .sync = "test" |
v-htmlとは?
画面にそのままhtmlタグを適用して出力させる事ができます。なので、v-textではできない文書内での改行の出力なんかに使われていたりします。
注意点
タグを解釈して実行させることになるので、JavaScriptコードを実行するXSSの脆弱性にもつながってしまいます。なので、v-htmlを利用する際は必ずユーザーからの入力をそのまま出力させるようなコードにはならないようにしましょう。
renderとは?
Vue.jsでレンダリングの制御ができる機能のことです。
renderの使い方
1 2 3 4 5 6 7 8 9 |
<render method="レンダリング関数名" :args="引数"></render> new Vue({ methods:{ レンダリング関数:function(args){ return arg } } }) |
「renderタグ」を使って、その属性の中で「レンダリング関数」を呼ぶ必要があります。
レンダリング関数
レンダリングをする内容を返す必要があります。
レンダリング内容を生成する。
第一引数にタグ名、第二引数にタグ内容を指定すれば動的にタグを生成することも可能です。下記を実行すると<div id="app2">の中にpタグが生成されます。なお、下記の例ではレンダリング関数名を「args」としていますが、実際には「h」と記載されることも多いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<div id="app2"> </div> <script> const txt = "テキスト"; new Vue({ el: '#app2', data: { message: "テスト", text: txt }, render: function (args) { return args('p', 'レンダーテスト'); } }) </script> |
レンダリング関数で返されている値について
VNodeという仮想DOMが返されています。
引数にオブジェクトも取れる。
下記はES6の記述方法になっていますが、render関数の引数にはオブジェクト(App.vueというオブジェクト)も取れます。
1 2 3 4 5 6 7 8 |
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app') |
この記事へのコメントはありません。