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

最終更新日
2017.11.17

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

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

  • Vue 2.5.4

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

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

<script src="https://cdn.jsdelivr.net/npm/vue"></script>

この URL は常に最新のバージョンを開発モードでロードします。開発モードだと細かいエラーを表示してくれます。運用には min ファイルを使いましょう。

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

Vue.js は必ずしも Webpack などのビルド環境を必要としないので手軽に始められます。

Vue インスタンスを作る

まずは Vue コンストラクタ関数を new してルートのインスタンスを作成します。

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

要素がないと怒られる場合は body タグの後など DOM が読み込まれたあとに実行するといいです。変数化しておく事で > vm.message = "test" という感じにコンソールや外部からアクセス出来ます。

コンストラクタのオプションには、Vue.js で使用するデータ、メソッド、マウント(配置)する要素などが指定できます。いくつか紹介。

  • el マウントする要素のセレクタ
  • data Vue.js で扱うデータ
  • methods アプリケーションで使用するメソッド

いつ new Vue すればいいの?

ところでこの Vue コンストラクタ関数はどのタグで使えば良いのでしょう?これ初めてだと意外と分からない。Vue を始めた頃 slack で質問してみたら丁寧に教えてもらえました。

基本は1つのアプリケーション、例えばブログだったらブログ全体に Vue のルートインスタンスを1つだけ作って、コンポーネントで部品を増やしていくやり方が良いよ★

と言うことです。部品を作るコンポーネントという機能があるので、メニューやフォームというように部品毎に new Vue するわけではないようです。となるとコンポーネントの扱い方はほぼ必須なので早めに覚えた方がよさそう。

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

何かしら操作したいデータはオプションの data に入れて使います。

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

deta に登録されているデータはインスタンス作成時に自動でリアクティブなデータに変換され、変化の監視が出来るようになります。

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

Vue で使用する HTML は読み込み時にパースされ 仮想DOM として Vue が保管しているのでタグで囲んでいないテキストも操作する事ができます。

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

Vue で持っているデータやメソッドはそのままの名前でテンプレートに使用したり実行する事ができます。

データを表示するには変数名を {{ message }} このような2つの大カッコで囲み、これは Mustache(マスタッシュ)と呼ばれるものです。両端のスペースは見やすくするためだけなのであってもなくてもOK。

現在ルートに message というデータを持っているので、その値の「Vue.js!」というテキストが表示されます。

インスタンスメソッドなどからデータを使用する場合 this.message というように this を付けます。

new Vue({
  el: '#app',
  data: {
    message: 'Vue.js!'
  },
  created: function() {
    alert(this.message)
  }
})

createdライフサイクルメソッドのひとつ。

データを HTML として表示する

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

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

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

テンプレート構文

プロフィールやコメントなどユーザーが入力したデータをそのまま v-html で展開したり、勿論テンプレートに使用してはいけない。 基本的な JavaScript の XSS 対策と一緒ですね。

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

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

<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 ディレクティブは初回だけ評価しそれ以降は静的コンテンツとして扱われ後から message が変わっても要素は更新されません。

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

表示したあとは監視する必要がなくなったり、操作が不要なコンテンツを静的化するためパフォーマンスの改善に活用していくといいです。

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

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

入力フォームとデータの紐付けには v-model ディレクティブを使用します。

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

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

new Vue({
  el: '#app3',
  data: {
    message: 'こんにちは'
  }
})

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

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

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

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

少し凝ったアプリケーションを作るなら当然単純なテキストばかりではないので、色々な形式のデータを持たせてそれを表示してみましょう。

配列の表示

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

new Vue({
  el: '#app4',
  data: {
    list: ['りんご', 'ばなな', 'いちご']
  }
})

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

<div id="app4">
  <ul>
    <li v-for="val in list">{{ val }}</li>
  </ul>
</div>

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

オブジェクトの表示

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

new Vue({
  el: '#app5',
  data: {
    list: {
      a: 'ハンバーグ',
      b: '焼肉',
      c: 'パスタ'
    }
  }
})

カッコを使うとオブジェクトは値とキーとインデックス、配列の場合は値とインデックスが取得できます。

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

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

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

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

new Vue({
  el: '#app6',
  data: {
    list: [
      { name: 'とまと', price: '100' },
      { name: 'れたす', price: '200' },
      { name: 'きゅうり', price: '300' }
    ]
  }
})

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

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

v-bind:key でID等のユニークなキーを指定しておくのが推奨されています。もしこのリストが更新された時リスト内の差分のみ再描画をするようになるので後から操作したいなら付けておくといいです。

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