0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue3のpropsについて調べてみた

Last updated at Posted at 2025-09-17

基本的な使い方

<script setup>内でpropsを受け取るには、definePropsを使用します。これはインポートせずに直接利用できます。

配列構文

最もシンプルな方法は、propsの名前を文字列の配列で指定するものです。

ChildComponent.vue
<script setup>
// 'message' という名前のpropsを受け取る
const props = defineProps(['message']);

console.log(props.message); // 親から渡された値
</script>

<template>
  <p>{{ message }}</p>
</template>
ParentComponent.vue
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

<template>
  <ChildComponent message="こんにちは、Vue 3!" />
</template>

この例では、親から渡された"こんにちは、Vue 3!"という文字列が、子コンポーネントのmessageというpropとして受け取られます。


型を指定する(オブジェクト構文)

より堅牢なコードにするために、各propに型を指定することが推奨されます。

JavaScriptでの型指定

String, Number, Boolean, Array, Object, Date, Function, Symbol といったネイティブコンストラクタを型として使用できます。

ChildComponent.vue
<script setup>
const props = defineProps({
  title: String, // String型
  likes: Number, // Number型
  isPublished: Boolean, // Boolean型
});
</script>

<template>
  <div>
    <h2>{{ title }}</h2>
    <p>いいね数: {{ likes }}</p>
    <p>{{ isPublished ? '公開中' : '非公開' }}</p>
  </div>
</template>

TypeScriptでの型指定

TypeScriptを使っている場合は、ジェネリクス(< >)を使ってより厳密に型を定義できます。こちらの方がIDEの補完も効きやすく、開発体験が向上します。

ChildComponent.vue
<script setup lang="ts">
// 型をインターフェースや型エイリアスとして定義
interface Props {
  title: string;
  likes?: number; // '?' をつけるとオプショナルになる
}

const props = defineProps<Props>();
</script>

Propsのリアクティビティと注意点 ⚠️

propsはリアクティブなオブジェクトです。親コンポーネントでデータが変更されると、子コンポーネントのpropsも自動的に更新されます。

しかし、よくある間違いとしてpropsを分割代入してしまうケースがあります。

import { defineProps } from 'vue';

const props = defineProps(['message']);

// 🚨 これはNG! リアクティビティが失われる
let { message } = props;

// 親コンポーネントでmessageが変更されても、このmessage変数の値は更新されない

分割代入をすると、その変数はリアクティビティを失い、ただの文字列や数値になってしまいます。

Vue 3.5以降での改善 🎉

Vue 3.5以降では、propsの分割代入がリアクティビティを維持するようになりました!

ChildComponent.vue
<script setup>
const props = defineProps(['message']);

// ✅ Vue 3.5以降では、これでリアクティビティが維持される
const { message } = props;

// 親コンポーネントでmessageが変更されると、このmessage変数も自動的に更新される
</script>

<template>
  <p>{{ message }}</p>
</template>

この改善により、toRefsを使わずに直接分割代入できるようになり、コードがよりシンプルになりました。

Vue 3.4以前でのリアクティビティを維持する方法

Vue 3.4以前では、propsの特定のプロパティをリアクティブなまま扱いたい場合は、toRefsまたはtoRefユーティリティを使用する必要がありました。

ChildComponent.vue
<script setup>
import { toRefs } from 'vue';

const props = defineProps({
  message: String,
});

// propsオブジェクト内の各プロパティをリアクティブなrefに変換
const { message } = toRefs(props);

// これでmessageはリアクティブなrefとして扱える
// .valueで値にアクセスする必要がある (template内では不要)
console.log(message.value);
</script>

<template>
  <p>{{ message }}</p>
</template>

ポイント: 基本的にpropsはそのままprops.プロパティ名の形で使うのが安全です。ロジックの都合でどうしても分割したい場合にtoRefsを使いましょう。


デフォルト値とバリデーション

propsにはデフォルト値を設定したり、必須項目にしたり、独自の検証ルールを追加したりできます。これらはオブジェクト構文で行います。

UserProfile.vue
<script setup lang="ts">
interface Props {
  name: string;
  age?: number;
  role: 'admin' | 'user' | 'guest';
}

// withDefaults を使ってデフォルト値を設定
const props = withDefaults(defineProps<Props>(), {
  age: 20,
  role: 'user',
});
</script>

JavaScriptの場合は、より詳細なバリデーションが可能です。

UserProfile.js.vue
<script setup>
defineProps({
  name: {
    type: String,
    required: true, // 必須項目
  },
  age: {
    type: Number,
    default: 20, // デフォルト値
  },
  role: {
    type: String,
    // 値が指定されたいずれかであるかを検証
    validator: (value) => {
      return ['admin', 'user', 'guest'].includes(value);
    },
    default: 'user',
  },
});
</script>

これらの機能を活用することで、コンポーネントの再利用性が高まり、予期せぬエラーを防ぐことができます。

0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?