最終更新日:191207 原本2019-09-02

「Nuxt.js」の基本、「Vue.js」の利用方法を知ろう

JavaScriptフレームワーク「Vue.js」と「Nuxt.js」の活用 第2回

 本連載では、Webページのユーザーインタフェース(UI)フレームワーク「Vue.js」と、Vue.jsを利用してWebページを作成できるフレームワーク「Nuxt.js」の活用方法を、サンプルとともに紹介します。前回はVue.jsとNuxt.jsの概要を説明しました。今回はNuxt.jsでUI構築に利用するVue.jsについて、基本的な利用方法を説明します。

はじめに

 Nuxt.jsは、Webページのユーザーインタフェース(UI)フレームワークであるVue.jsに、Webページの作成に必要なUI以外の機能を追加して、まとめて提供するフレームワークです。そのため、Nuxt.jsの機能を使いこなすためには、まずVue.jsの利用方法を知っておく必要があります。

 Vue.jsでは、データとWebページの表示を関連付けるデータバインディングやイベント処理、条件分岐や繰り返しなど、動的なWebページを作成するための機能が提供されます。本記事では、こういったVue.jsの基本的な利用方法を説明します。

対象読者

  • Nuxt.jsを何から始めていいかわからない方
  • Vue.js未経験の方
  • ひとまずVue.jsやNuxt.jsで動的なWebページを作ってみたい方

必要な環境

 本記事のサンプルコードは、以下の環境で動作を確認しています。

  • Windows 10 64bit版 
    • Node.js v10.16.2 64bit版
    • Nuxt.js 2.8.1
    • Vue.js 2.6.10
    • Microsoft Edge 44.18362.1.0

 サンプルコードは、Nuxt.jsのCLIツール(create-nuxt-app)で生成したプロジェクトをもとに実装しています。CLIツールの利用法やプロジェクト構成などの詳細は、前回記事を参照してください。

 サンプルコード を実行するには、サンプルのフォルダーで「npm install」コマンドを実行してライブラリーをダウンロード後、「npm run dev」コマンドを実行して、Webブラウザーで「http://localhost:3000/」を開きます。

Webページとデータを関連付けるVue.jsのデータバインディング(1)

 動的なWebページでは、ユーザーの入力をデータに反映したり、データをWebページに表示したりする処理が必要となります。Vue.jsではこういった処理を、Webページとデータを関連付ける「データバインディング」で実現します。

データバインディングの基本

 Vue.jsでデータバインディングを行う基本的な方法を、図1のサンプルで説明します。テキストボックスに入力されたURLを、ハイパーリンクの文言とリンク先に反映します。

図1:基本的なデータバインディングのサンプル(p001-binding-basic)
図1:基本的なデータバインディングのサンプル(p001-binding-basic)

 図1のWebページを実装したファイルの内容を、リスト1に示します。

[リスト1]基本的なデータバインディングの記述(p001-binding-basic/pages/index.vue)
<template>
  <div class="container">
    <h1>基本的なデータバインディング</h1>
      <input v-model="url" placeholder="URL"> <!--(1)-->
      <a v-bind:href="url" target="_blank"> <!--(2)-->
        {{ url }}へのリンク <!--(3)-->
      </a>
  </div>
</template>
<script>
export default {
  data() {
    return {
      url: 'https://codezine.jp/' // (4)
    }
  }
}
</script>
(以下略)

 ロジックを記述する<script>で、URLの文字列を格納するurl変数(4)を定義します。表示内容のテンプレートを記述する<template>では、(1)~(3)の3種類の方法でurl変数を参照しています。(1)の「v-model」はテキストボックスのような入力部品の内容、(2)の「v-bind」はhrefなどのタグ属性、(3)の{{ }}(2重の中カッコ)はWebページの表示内容に、変数内容を関連付け(データバインディング)します。このうちv-modelは、入力部品の内容と変数の内容を双方向に同期する、いわゆる双方向データバインディングを実現します。

 v-modelやv-bindのように「v-」から始まってHTMLタグに設定するVue.jsの属性を「ディレクティブ」と呼びます。以下では、v-modelとv-bindディレクティブについて補足説明していきます。

Webページとデータを関連付けるVue.jsのデータバインディング(2)

さまざまな入力部品とv-modelディレクティブ

 さまざまな入力部品でv-modelディレクティブを利用する例を、図2のサンプルで説明します。入力部品に入力した内容が、入力部品のすぐ下に表示されます。

図2:v-modelディレクティブのサンプル(p002-v-model)
図2:v-modelディレクティブのサンプル(p002-v-model)

 図2で利用しているv-modelディレクティブの記述をリスト2に示します。

[リスト2]さまざまな入力部品に対するv-modelディレクティブの記述(p002-v-model/pages/index.vue)
<h3>テキストボックス</h3> <!--(1)-->
<input v-model="text1">

<h3>複数行テキストボックス</h3> <!--(2)-->
<textarea v-model="text2"></textarea>

<h3>チェックボックス</h3> <!--(3)-->
<input type="checkbox" id="checkbox" v-model="checkboxValue">
<label for="checkbox">私はNuxt.jsが好き</label>

<h3>ラジオボタン</h3> <!--(4)-->
<input type="radio" id="radio1" value="vue" v-model="radioValue">
<label for="radio1">Vue.js</label>
<input type="radio" id="radio2" value="angular" v-model="radioValue">
<label for="radio2">Angular</label>
<input type="radio" id="radio3" value="react" v-model="radioValue">
<label for="radio3">React</label>

<h3>選択</h3> <!--(5)-->
<select v-model="selectValue">
  <option disabled value=""></option>
  <option value="vue">Vue.js</option>
  <option value="angular">Angular</option>
  <option value="react">React</option>
</select>

<h3>複数チェックボックス</h3> <!--(6)-->
<input type="checkbox" id="checkbox1" value="vue" v-model="checkboxArray">
<label for="checkbox1">Vue.js</label>
<input type="checkbox" id="checkbox2" value="angular" v-model="checkboxArray">
<label for="checkbox2">Angular</label>
<input type="checkbox" id="checkbox3" value="react" v-model="checkboxArray">
<label for="checkbox3">React</label>

<h3>複数選択</h3> <!--(7)-->
<select v-model="selectArray" multiple>
  <option value="vue">Vue.js</option>
  <option value="angular">Angular</option>
  <option value="react">React</option>
</select>

 テキストボックスは、通常の(1行の)テキストボックス(1)のほか、<textarea>タグによる複数行テキストボックス(2)でも同様にv-modelディレクティブが利用できます。

 (3)はチェックボックスの例です。v-modelで設定した変数に、チェック状態(trueまたはfalse)が格納されます。

 (4)のラジオボタンや(5)の選択では、選択されたラジオボタンや選択肢に対応する値(value属性の値)が、v-modelで設定した変数に格納されます。

 複数選択に対応した(6)のチェックボックスや(7)の選択では、v-modelに配列変数を設定すると、選択された複数の値が配列に格納されます。

[補足]v-modelディレクティブの修飾子

 v-modelディレクティブには、入力内容が確定した時のみデータを更新する「.lazy」、入力内容を数字に変換する「.number」、入力された文字列前後の空白を削除する「.trim」の修飾子を付与できます。修飾子を付与する例をリスト3に示します。

[リスト3]v-modelディレクティブに修飾子を付与する例(p002a-v-model-modifier/pages/index.vue)
<input v-model.number="number1">

 修飾子の詳細は、公式ドキュメントを参照してください。

v-bindディレクティブでクラスやスタイルを設定

 v-bindディレクティブを利用すると、HTMLタグの任意の属性に、Vue.jsの変数内容を反映させられます。特に、CSSのクラス(class属性)とスタイル(style属性)では、JavaScriptオブジェクトを利用してより詳細な設定ができます。この例を、図3のサンプルで説明します。チェックボックスでクラスの適用有無を切り替えたり、テキストボックスでスタイル(文字色)を設定したりできます。

図3:v-bindディレクティブでCSSのクラスやスタイルを設定するサンプル(p003-v-bind)
図3:v-bindディレクティブでCSSのクラスやスタイルを設定するサンプル(p003-v-bind)

 まず、class属性のデータバインディング記述を、リスト4に示します。

[リスト4]class属性のデータバインディング記述(p003-v-bind/pages/index.vue)
<label for="checkbox1" v-bind:class="{ 'color-red' : isChecked }">
  文字を赤色にする
</label>

 v-bind:classに設定された「{ 'color-red' : isChecked }」は、isChecked変数がtrueの時に、CSSクラス「color-red」が適用されることを意味します。この記述で、適用されるCSSクラスを条件によって切り替えられます。

 次に、style属性のデータバインディング記述を、リスト5に示します。

[リスト5]style属性のデータバインディング記述(p003-v-bind/pages/index.vue)
<div v-bind:style="{ color: fontColor }">
  色:{{ fontColor }}
</div>

 v-bind:styleに設定された「{ color: fontColor }」は、CSSのcolorプロパティに、fontColor変数の内容を設定することを意味します。サンプルではfontColor変数がテキストボックスにデータバインディングされているため、テキストボックスに色名を入力すると、色名に対応した色で文字列が表示されます。

[補足]算出プロパティの利用

 Vue.jsでは、算出プロパティ(変数をもとに算出した読み取り専用のプロパティ)を定義できます。例えば、リスト4、5でv-bindディレクティブに設定されている内容は、リスト6の通り算出プロパティにできます。

[リスト6]算出プロパティの定義(p003-v-bind/pages/index.vue)
export default {
(略)
  computed: { // 算出プロパティ
    computedClass() {
      return { 'color-red' : this.isChecked };  // this.isCheckedから算出
    },
    computedStyle() {
      return { color: this.fontColor };         // this.fontColorから算出
    }
  }
}

 リスト6の算出プロパティcomputedClass、computedStyleは、リスト7の通りv-bindディレクティブに設定できます。

[リスト7]v-bindディレクティブに算出プロパティを設定(p003-v-bind/pages/index.vue)
<!-- class -->
<label for="checkbox1" v-bind:class="computedClass">
  文字を赤色にする
</label>
<!-- style -->
<div v-bind:style="computedStyle">
  色:{{ fontColor }}
</div>

v-onディレクティブによるイベント処理

 Vue.jsのイベント処理は、v-onディレクティブを利用して「v-on:<イベント名>」形式で記述します。v-onディレクティブの利用方法を、ボタンのクリックとキー入力のイベントハンドラーを実装した図4のサンプルで説明します。

図4:v-onディレクティブのサンプル(p004-v-on)
図4:v-onディレクティブのサンプル(p004-v-on)

 v-onディレクティブには、イベントハンドラーのメソッド名を設定します。リスト8では、クリックイベントに対応する「v-on:click」に、イベントハンドラーのgreetメソッドを設定しています。

[リスト8]v-onディレクティブの記述(p004-v-on/pages/index.vue)
<button v-on:click="greet">ご挨拶</button>

 イベントハンドラーに与える引数を含めてv-onディレクティブに設定することもできます。特に、JavaScriptのイベント変数が必要な場合は、引数に「$event」を設定します。リスト9では、キーが押下後に離された時のイベント「v-on:keyup」のイベントハンドラーで、押下されたキーの文字列をイベント変数から取得して画面に表示します。処理の詳細はサンプルコードを参照してください。

[リスト9]イベント変数を利用する場合の記述(p004-v-on/pages/index.vue)
<input v-on:keyup="onKeyUp($event)">

[補足]イベント修飾子とキー修飾子

 v-onディレクティブには、イベント処理の内容を補足する「イベント修飾子」を追加できます。フォームのサブミットボタンにクリックイベントを設定したリスト10の例では、v-on:clickに「.prevent」というイベント識別子を追加して、デフォルトの動作(=フォームのSubmit)をキャンセルしています(イベント変数のpreventDefaultメソッドと同じ効果です)。

[リスト10]イベント修飾子の記述(p004a-v-on-modifier/pages/index.vue)
<form>
  <input type="submit" v-on:click.prevent="onFormSubmit" value="Submitボタン">
</form>

 また、v-onディレクティブに「キー修飾子」を追加して、特定のキーに対するイベントを設定できます。リスト11では、v-on:keyupに「.enter」というキー修飾子を追加して、Enter(改行)キーが押下された場合のみkeyupイベントが発生するようにしています。

[リスト11]キー修飾子の記述(p004a-v-on-modifier/pages/index.vue)
<input v-on:keyup.enter="onKeyUpEnter">

 イベント修飾子やキー修飾子の詳細は、イベントに関する公式ドキュメントを参照してください。

[補足]v-bindとv-onの省略記法

 v-bindとv-onでは省略記法を利用できます。省略記法では、「v-bind:href」を「:href」、「v-on:click」を「@click」と記述します。

条件分岐と繰り返し

 Vue.jsでは、「v-if」ディレクティブで条件分岐、「v-for」ディレクティブで繰り返しを利用できます。以下で利用方法を説明していきます。

v-ifディレクティブによる条件分岐

 v-ifディレクティブの利用方法を、図5のサンプルで説明します。ラジオボタンの選択で、表示される文言の内容が変わります。

図5:v-ifディレクティブのサンプル(p005-v-if)
図5:v-ifディレクティブのサンプル(p005-v-if)

 図5のサンプルにおけるv-ifディレクティブの記述を、リスト12に示します。

[リスト12]v-ifディレクティブの記述(p005-v-if/pages/index.vue)
<div v-if="radioValue === 'ios'"> <!--(1)-->
  あなたはiOSが好きなんですね。
</div>
<div v-else-if="radioValue === 'android'"> <!--(2)-->
  あなたはAndroidが好きなんですね。
</div>
<div v-else> <!--(3)-->
  その他が好きとはマニアックですね。
</div>

 (1)のv-ifディレクティブで、ラジオボタンの選択値が格納されるradioValueが「ios」の場合に表示される内容を記述します。v-ifディレクティブの直後に、(2)のv-else-ifディレクティブや、(3)のv-elseディレクティブを記述すると、複数条件の分岐を記述できます。

v-forディレクティブによる繰り返し

 v-forディレクティブの利用方法を、図6のサンプルで説明します。配列に格納されたスマートフォンの情報を一覧表示します。

図6:v-forディレクティブのサンプル(p006-v-for)
図6:v-forディレクティブのサンプル(p006-v-for)

 スマートフォンの情報を格納するphoneList配列は、<script>でリスト13の通り記述して、id、vendor、modelのプロパティを含むJavaScriptオブジェクトの配列を設定します。

[リスト13]phoneList配列の設定(p006-v-for/pages/index.vue)
phoneList: [
  { id: 1, vendor: 'Apple', model: 'iPhone XS' },
  { id: 2, vendor: 'Apple', model: 'iPhone XS Max' },
(略)
]

 phoneList配列の内容を一覧表示するv-forディレクティブの記述は、リスト14の通りです。

[リスト14]v-forディレクティブの記述(p006-v-for/pages/index.vue)
<ul>
  <li v-for="phone in phoneList" v-bind:key="phone.id"> <!--(1)-->
    {{ phone.vendor }}: {{ phone.model }} <!--(2)-->
  </li>
</ul>

 (1)でv-forディレクティブに「phone in phoneList」と設定すると、phoneList配列の各要素をphone変数として取得できるので、(2)の通り{{ }}記述でphone変数のプロパティを指定して画面表示できます。

 なお、リスト14(1)の「v-bind:key」は、リストの各データを一意に表すキーとなるデータ項目を設定する記述です。Vue.jsはv-bind:keyに設定された項目で各データを一意識別して、配列の更新時に、更新された箇所だけを再描画します。

まとめ

 本記事では、JavaScriptフレームワークNuxt.jsがUIの構築に利用するVue.jsについて、基本的な利用方法を説明しました。データバインディングやイベント処理、条件分岐や繰り返しの機能を利用して、動的なWebページをVue.jsの機能で作成できます。

 次回は、Webページ遷移を実現する、Nuxt.jsのルーティング機能を説明します。

参考資料