LoginSignup
4
3

More than 3 years have passed since last update.

なるはや Vue SPA入門:コンポーネント

Last updated at Posted at 2019-07-15

Vue CLI3 で作成した SPA(Single Page Application)プロジェクト上で、段階的に Vue.js を学んで行きましょう。

目次はこちら

今回はコンポーネント編です。
TodoList を作りながらコンポーネントの使い方を学びます。

前提事項

Vue の基本 が完了していること。

ページの追加

新規に Todo List ページを作成します。

  • TodoList.vue を作成
  • router.js を修正
  • App.vue にナビゲーションを追加

やり方を忘れてしまった人は「Vue Router 編」を振り返ってください。

src/views/TodoList.vue
<template>
  <div class="todolist">
    <h1>Todo</h1>
    <ul v-if="todos.length">
      <li
        v-for="todo in todos"
        :key="todo.id"
      >{{ todo.text }}</li>
    </ul>
    <p v-else>
      TODO 一覧はありません
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      todos: [
        { id: 1, text: "Learn Vue" },
        { id: 2, text: "Learn about single file components" },
        { id: 3, text: "Learn about components" }
      ]
    };
  }
};
</script>

<style>
h1 {
  text-align: center;
}

.todolist {
  max-width: 400px;
  margin: 0 auto;
  text-align: left;
}
</style>

コンポーネントの作成とプロパティによる値渡し

Todo List から Todo List Item を別コンポーネントに切り出します。

TodoListItem.vue コンポーネントを作成します。

src/components/TodoListItem.vue
<template>
  <!-- todo プロパティのテキストを表示 -->
  <li>{{ todo.text }}</li>
</template>

<script>
export default {
  // 親コンポーネントから todo プロパティを受け取る
  props: ["todo"]
};
</script>

親コンポーネントから子コンポーネントに値を渡すにはプロパティを使用します。
上記では todo プロパティを受け取れるよう宣言しています。

TodoList.vue を下記の様に修正します。

TodoList.vue
<template>
  <div class="todolist">
    <h1>Todo</h1>
    <ul v-if="todos.length">
      <!-- TodoListItem コンポーネントを使います -->
      <!-- v-bind を使って動的に todo プロパティを渡します -->
      <TodoListItem
        v-for="todo in todos"
        :key="todo.id"
        :todo="todo"
      />
    </ul>
    <p v-else>
      TODO 一覧はありません
    </p>
  </div>
</template>

<script>
// TodoListItem コンポーネントを import します
import TodoListItem from "../components/TodoListItem";

export default {
  // 使用するコンポーネントを Vue に伝えます
  components: {
    TodoListItem
  },
  data() {
    // ...
  }
};
</script>

<style>
/* ... */
</style>

JavaScript のところで先程作成したTodoListItem.vueをインポートして、Vue オブジェクトのcomponents属性に設定しています。こうすることで、HTML のところで、TodoListItemタグが使用できるようになります。

HTML のところではliタグの代わりにTodoListItemタグを使用するように変更しました。子コンポーネントに値を渡すためにtodoプロパティにtodoオブジェクトをバインドしています。

プロパティのバリデーション

プロパティは以下のように記述することでバリデーションチェックをすることができます。

export default {
  props: {
    // 基本的な型の検査 (`null` と `undefined` は全てのバリデーションにパスします)
    propA: Number,
    // 複数の型の許容
    propB: [String, Number],
    // 文字列型を必須で要求する
    propC: {
      type: String,
      required: true
    },
    // デフォルト値つきの数値型
    propD: {
      type: Number,
      default: 100
    },
    // デフォルト値つきのオブジェクト型
    propE: {
      type: Object,
      // オブジェクトもしくは配列のデフォルト値は
      // 必ずそれを生み出すための関数を返す必要があります。
      default: function () {
        return { message: 'hello' }
      }
    },
    // カスタマイズしたバリデーション関数
    propF: {
      validator: function (value) {
        // プロパティの値は、必ずいずれかの文字列でなければならない
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
}

TodoListItem.vue もバリデーションチェックをするよう修正します。

TodoListItem.vue
props: {
  todo: {
    type: Object,   // オブジェクト型であること
    required: true  // 必須項目
  }
}

イベント

親コンポーネントから子コンポーネントへはプロパティを使って値を渡すことができますが、子コンポーネントから親コンポーネントへ値を渡すことは出来ません。その代わりにイベントを使って通信することができます。

イベントの発火

TodoListItem.vue に削除ボタンを設け、removeイベントを発火するよう修正します。

TodoListItem.vue
<li>
  {{ todo.text }}
  <button @click="$emit('remove', todo.id)">x</button>
</li>

botton がクリックされると $emit('イベント名', ペイロード) でイベントを発火します。

イベントハンドリング

TodoList.vueremove イベントをハンドリングして Todo を削除します。

TodoList.vue
<!-- remove イベントをハンドリングして removeTodo メソッドをコールします -->
<TodoListItem
  v-for="todo in todos"
  :key="todo.id"
  :todo="todo"
  @remove="removeTodo"
/>
TodoList.vue
methods: {
  removeTodo(idToRemove) {
    this.todos = this.todos.filter(todo => {
      return todo.id !== idToRemove;
    });
  }
}

removeTodメソッドにはremoveイベントが発火された時のペイロードが引数として渡されます(この場合は todo の id です)。

演習

TodoInputText.vue コンポーネントを作成して、TodoList.vue でそれを使って TODO を追加できるようにしてください。

次回

Vue.js devtools

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3