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'
})

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

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

ところで、この Vue コンストラクタ関数はどのタグで使えば良いのでしょうか。今考えると初心者中の初心者の疑問なんですけど slack で質問してみたら丁寧に教えてもらえました。

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

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

動的に入れ替えたい文字列などはオプションオブジェクトの data に入れて使います。

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

Vue で使うデータやメソッドはスクリプトからは this.hoge という感じに this を使って参照出来ますが、テンプレートから使う場合は this は省略します。

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

Vue で扱う DOM はパースされて保管しているのでタグで囲んでいないテキストも操作する事が可能です。

<!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つの大カッコで囲みます。両端のスペースは見やすくするためだけなのであってもなくてもOKです。現在ルートに 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度だけ展開されそれ以降は静的コンテンツとして扱われ後から message が変わっても要素は更新されません。

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

よくサンプルにあるリアルタイムに連動するやつ

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

入力フォームの値と紐付けるデータを v-model ディレクティブで指定します。

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

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

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

v-から始まるディレクティブ

ここまでにも v-bindv-html など出てきましたが、これから Vue.js の独自の属性(ディレクティブ) v-なんちゃら というものが色々出てきます。これは Vue.js での特別な役割を持った属性です。そして、v- から始まる属性の値はテキストではなく「JavaScript の式」というのがポイントです。他にも Vue.js 独自の属性はありますが、 v- から始まっていなければ値はただのテキストです。v-pre など値が無いものは特に考えなくてもOKです。

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

配列の表示

以下のような 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等のユニークなキーを指定しておくのが推奨されてます。(キーの役割は色々あって今後の記事で書いています)

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