Vue.js で文字やリストを動的に表示する

Vue.js の導入と Vue を使ってテキストや配列などのデータを動的に表示します。

まずは Vue.js を使えるようにする

学習で簡単に試したい場合は CDN を利用するのが一番簡単ですね!

公式サイトの「はじめる」を読むと最初に紹介されています。

<script src="https://unpkg.com/vue/dist/vue.js"></script>

ローカル環境以外にも https://jsfiddle.net/ を利用する方法も紹介されています。サンプルを試したりお試しで書く場合手軽でおすすめです。

Vueインスタンスを作る

var vm = new Vue({
el: '#app'
})

まずは new でルートのインスタンスを作成します。返り値はルートのビューモデルです。変数に入れておくと > vm.piyo = "test" みたいにコンソールでアクセス出来るので動作テストする時に便利です。要素がないよと怒られる場合は body タグの後などドキュメント DOM が読み込まれたあとに実行するといいです。

インスタンスを作成する時にオブジェクトでオプションを渡せます。el にはどこにマウントするか要素のセレクタを指定しますが、作成時に省略して任意のタイミングで vm.$mount('#app') とマウントする事もできます。

ところで、この Vue インスタンスはどのタグで使えば良いのでしょうか。slack で質問してみたところ、1つのアプリケーション、例えばブログだったらブログ全体に Vue インスタンスを1つだけ作って、コンポーネントで部品を増やしていくやり方が良いよ★と言うことでした。メニューやフォームというように部品毎にインスタンスを作るわけじゃないんですね!そうなるとコンポーネントの扱い方はほぼ必須なので早めに覚えないとだめみたいですね。

データはプロパティから使う

動的に入れ替えたい文字列などはインスタンス作成時の data オプションに入れて使います。

var vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!' ← このデータを使う
}
})

単純なテキストを表示する

アプリケーションに必要な DOM はパースされて Vue で保管しているのでタグで囲んでいないテキストも操作する事が可能です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>

データを表示するには変数名を {{ message }} このような2つの大カッコで囲みます。両端のスペースは見やすくするためだけっぽいのであってもなくてもいいようです。現在ルートのデータに message を持っているので、その値の「Hello Vue.js!」が表示されます。

データをHTMLで表示する

データを DOM に配置した時は XSS 対策で HTML はエスケープされテキストとして表示されます。信頼出来るデータを HTML として表示したい場合は以下のように記述します。

<span v-html="message"></span>

XSS 脆弱性を容易に引き起こすので、ウェブサイトで動的に任意のHTMLを描画することは、非常に危険です。信頼できるコンテンツにだけ HTML 展開を利用してください。ユーザーから提供されたコンテンツに対しては決して使用してはいけません。

テンプレート構文

要素の属性部分にデータを使用する

テキストと同じ感覚で以下のように書いても展開されません。

<p><a href="{{ url }}">{{ message }}</a></p> <!-- ★これはURLが展開されない -->

属性にデータを使用したい場合は v-bind ディレクティブを使ってバインドします。

<p><a v-bind:href="url">{{ message }}</a></p>

また v-bind: で省略する事が出来ます。バインドさせる数が多い場合はスッキリ書けますね(๑'ᴗ'๑)

<p><a :href="url">{{ message }}</a></p>

最初のうちはわからなくなるので v-bind と書いておいて慣れてきたら省略するのが良いと思います。

一部の要素を Vue でパースしない

特定の要素以下を Vue でパースさせたくない&させる必要がない場合もあると思います。v-pre ディレクティブを使用するとプレーンな HTML と認識してくれるので動的なコンテンツを含まない場合指定してしておくとパフォーマンスが上がったりします。 v-once ディレクティブは1度だけ展開されそれ以降は静的コンテンツとして扱われアクセスも出来なくなります。

<p><a v-bind:href="url" v-pre>{{ message }}</a></p> → 一切展開されないのでブラケットのまま表示
<p><a v-bind:href="url" v-once>{{ message }}</a></p> → 最初に message を表示して以降リアクティブを解除

このデモでは v-once を付けているのでさっきのようにコンソールから打ち込んでも更新されません。

よくサンプルにある入力と連動するやつをとりあえずやりたい

ちょっと順番が逸れますが、フレームワーク系のサンプルでよく見かけていた、更新されるのがリアルタイムに分かるフォームの入力やってみたかったのです。もちろんネイティブでも処理を書けば出来る事なんですけどこういうのを管理するのはとても大変…。

フォームアイテムに v-model ディレクティブで変数を指定します。

<div id="app">
<input v-model="message">
<p>{{ message }}</p>
</div>

ルートインスタンスのほうに hello でデータを作っておきます。

うーんテンションあがる!勉強も頑張れそうです\(*⁰▿⁰*)/ チェックボックスやセレクトメニューの場合どうなるんだろうとか色々知りたい事もありますが、このへんはもう少し基本を学んでから続きをやりたいと思います。

リストをループで表示する

配列の表示

以下のような test2list という単純な配列データを表示させます。

var vm = new Vue({
el: '#app',
data: {
test2list: ['りんご', 'ばなな', 'いちご'],
}
});

リストを表示するには v-for というディレクティブを使用します。

<ul>
<li v-for="val in test2list">{{ val }}</li>
</ul>

中身は普段 JavaScript でオブジェクトのループに使っている for in 文と一緒ですね。

オブジェクトの表示

次に以下のような単純なオブジェクトをループで表示させてみます。

var vm = new Vue({
el: '#app',
data: {
test3list: {
'a': 'ハンバーグ',
'b': '焼肉',
'c': 'パスタ'
},
}
});

カッコを使うとキーと値が一緒に受け取れます。配列の場合はインデックスが受け取れます。

<ul>
<li v-for="(val, key) in test3list">(Key:{{ key }}) {{ val }}</li>
</ul>

ブラウザによってオブジェクトの処理順は保証されないため、常にセットした順番どおりに表示したい場合は次のテストのようにオブジェクトをリスト化するとよいです。

オブジェクトのリストを表示

次にネストされた少し複雑なオブジェクトのリストをループで表示させてみます。

var vm = new Vue({
el: '#app',
data: {
test4list: [{
'name': 'とまと',
'price': '100'
}, {
'name': 'れたす',
'price': '200'
}, {
'name': 'きゅうり',
'price': '300'
}],
}
});

配列をループするのと同じなので、インデックスは不要なら取得しなくてもいいと思います。

<ul>
<li v-for="(val, idx) in test4list" v-bind:key="val.name">
(No:{{ idx }}) {{ val.name }} {{ val.price }}円
</li>
</ul>

 v-bind:key でID等のユニークなキーを指定しておくと更新するときとか検索効率が良いらしい。なお後からやるコンポーネントに v-for を使う場合は key は必須とのこと。

とりあえず、色々な種類のデータの表示方法を覚えました!次回は表示したデータを Vue を使って更新してみたいと思います。