2018.04.22

Vue.jsコンポーネント入門 (3) propsによるデータの受け渡し


本記事は Vue.js コンポーネント入門の第3回です。

props という機能でコンポーネントにデータを受け渡す方法を紹介します。

前提

PC ブラウザ Node npm Vue
macOS 10.12 Firefox Quantum 9.3.0 5.5.1 2.5

Getting started

第1回記事の通り環境構築を進めてください。

# プロジェクトディレクトリで以下のコマンドを実行してください。
$ git clone git@github.com:MasahiroHarada/vue-components-starter-kit.git chapter-3
$ cd chapter-3
$ npm install

props

前回の記事でコンポーネントは HTML 要素と考えられるという説明をしました。

props はその要素の属性と考えればよいでしょう。

例えば <a><img> などで、その要素の動作を指定するために、属性としてデータを渡すことがあるでしょう。<a> であれば href 属性で遷移先を指定します。<img> であれば src 属性で読み込む画像を指定します。

Vue コンポーネントにも同様の仕組みがあり、それが props です。

props の機能を学ぶために、<a> を真似た AnchorLink コンポーネントを作成しましょう。

コンポーネントファイルの作成

AnchorLink コンポーネントは href(遷移先)と text(表示テキスト)という二つの属性を受け取ります。

src/components/AnchorLink.vue
<template>
  <span class="anchor" @click="onClickLink">{{ text }}</span>
</template>

<script>
export default {
  props: {
    text: String,
    href: String
  },
  methods: {
    onClickLink () {
      window.location.href = this.href
    }
  }
}
</script>

<style scoped>
.anchor {
  color: blue;
  cursor: pointer;
  text-decoration: underline;
}
</style>

<template> にマークアップ、<script> に JavaScript、そして <style> に CSS を記述します。

<script> に注目してください。ここに記述する JavaScript は Vue インスタンスの設定オブジェクトをエクスポートしなければいけません。そして設定オブジェクトを見ると、props というプロパティが登場しています。

props プロパティはコンポーネントが扱うことのできる属性のリストを表すオブジェクトです。オブジェクトのキーが属性名で値が検証要件です。

検証要件とは、渡される属性値が満たすべき条件です。検証要件の書き方は何通りかありますが、ここでは最もシンプルに型のみを指定しており、hreftextString 型である必要があると定義しています。

そのほかの検証要件の記述方法については公式マニュアルを参照してください。

また、検証要件を書かずに属性名だけを配列で指定する方法もあります。しかし、公式のスタイルガイドでは props の定義をできる限り詳細に書くことが「必須」にカテゴライズされていますので、検証要件は積極的に記述しましょう。

コンポーネントの登録

次に、作成したコンポーネントを使用する側のコンポーネントに登録するという作業が必要です。今回は Anchor コンポーネントを使用するのはルートコンポーネント(一番外側)ですので、 index.js で下記のように記述します。

src/index.js
import Vue from 'vue'

import AnchorLink from './components/AnchorLink.vue'

new Vue({
  el: '#app',
  components: {
    AnchorLink
  }
})

まず作成した AnchorLink コンポーネント(<script> 内でエクスポートした設定オブジェクト)をインポートします。

次に Vue インスタンス生成時の設定オブジェクトに components プロパティを記述し、コンポーネントを登録します。components プロパティはオブジェクトを値に取ります。登録されるコンポーネントを使用する際の名前(タグ名)がキーで、インポートしたコンポーネントそのものが値です。

今回の例では、キー(タグ名)と値が同名(AnchorLink)なので、ES2015 の省略記法を用いました。

では index.html 内で AnchorLink コンポーネントを使用してみましょう。

HTML 側でコンポーネントを使用する

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue Component Tutorial</title>
</head>
<body>
  <div id="app">
    <anchor-link
      href="https://qiita.com"
      text="Qiitaのページ"
    ></anchor-link>
  </div>
  <script src="./dist/main.js"></script>
</body>
</html>

AnchorLink.vue で定義した通り、href 属性と text 属性を記述しています。既存の HTML 要素と書き方は同じですね。

タグの名前がケバブケース(小文字ハイフン区切り)である点に注意してください。index.js では「AnchorLink」というパスカルケース(単語の先頭大文字)のタグ名で登録しましたが、実はパスカルケースで登録していたとしても、ケバブケースで使用することができるのです。

HTML は大文字小文字を区別できませんので、HTML ファイル内では Vue コンポーネントのタグ名はケバブケースで記述しましょう。

さて、ここまで書けたらアプリケーションを起動して、

$ npm run start

ブラウザ(http://localhost:9000)から確認してみてください。<a> っぽい感じになっていますでしょうか。

属性を追加する

リンクを新しいタブで開けるように props を追加します。

src/components/AnchorLink.vue
<template>
  <span class="anchor" @click="onClickLink">{{ text }}</span>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      required: true
    },
    href: {
      type: String,
      required: true
    },
    newTab: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    onClickLink () {
      if (this.newTab === true) {
        window.open(this.href, '_blank')
      } else {
        window.location.href = this.href
      }
    }
  }
}
</script>

<style scoped>
.anchor {
  color: blue;
  cursor: pointer;
  text-decoration: underline;
}
</style>

newTab 属性を真偽値として定義しました。デフォルト値は false(つまりリンクを新しいタブで開かない)です。

あわせてほかの2属性の検証要件も少し詳細に、必須である旨を記述しました。

HTML は以下の通りです。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vue Component Tutorial</title>
</head>
<body>
  <div id="app">
    <anchor-link
      href="https://qiita.com"
      text="Qiitaのページ"
      :new-tab="true"
    ></anchor-link>
  </div>
  <script src="./dist/main.js"></script>
</body>
</html>

Vue.js入門 (2) テンプレートでも触れましたが、属性値を単なる文字列ではなく JavaScript の値として渡したい場合は属性名の頭にコロン : を付加します。

今回は "true" という文字列を渡したいのではなく、true という JavaScript の真偽値を渡したいため、属性名の頭にコロンを付加して :new-tab と記述します。

また、タグ名と同様に属性名もケバブケースで記述していることに注意してください。AnchorLink.vue では newTab とキャメルケース(小文字で始まって単語の先頭は大文字)で定義していましたが、やはり HTML は大文字小文字を区別できませんので属性名もケバブケースで記述します。

余談ですが、逆に JavaScript 側ではなぜキャメルケースかというと、JavaScript での変数の命名習慣がキャメルケースだからです。言語それぞれの習慣や性質に従う必要がありますね。

CodeSandbox

最終的なコードはこちらです。


以上、本記事では Vue.js コンポーネント入門の第3回として、コンポーネントに属性を定義してデータを受け渡す方法を紹介しました。

関連記事

Vue.js コンポーネント入門(全7回)

Vue.js 入門(全7回)