📌

[Nuxt]Propsのメモ

に公開

はじめに

最近、Nuxtを勉強することになったので、そのついでに気になったことをメモをしていきながら勉強していこうと思います!!

というわけで、NuxtはVueを使うので、まずはVueのPropsを確認していこーかなと思いまーす!

なお、この記事はNuxt 3 フロントエンド開発の教科書を参考にしております。

Propsとは?

Vueには、Propsという機能があります。
これはデータを親のコンポーネントから子のコンポーネントへ渡すものです。

ちょっと分かりづらいので、図で考えてみます。

上の図では、親コンポーネントが子コンポーネントにデータを渡している様子を示しています。Propsを使うことで、親から子にデータを簡単に渡すことができます。

いつ使うの?

まずは、適当なコンポーネントを用意してみました。

ソースコードはこちらです。

これが子コンポーネントです。

components/UserCard.vue
<template>
  <div class="userCard">
    <h2> 田中太郎 </h2>
    <p> ID: 1 </p>
    <p> email: taro.tanaka@example.com </p>
  </div>
</template>

<style scoped>
.userCard {
  border: 1px solid green;
}
</style>

こっちは親コンポーネントです。

app.vue
<template>
  <div>
    <UserCard />
    <UserCard />
  </div>
</template>

実際に動かしてもらえば分かると思うのですが、本当にただのコンポーネントです。
ですが、このままだと田中太郎さんのデータしか表示されず、他の人のデータを表示することができないですよね?

これを解決するのがPropsです。

親コンポーネントにあるデータを子コンポーネントに渡すことでいろいろなデータを表示することができるんです。

Propsを送信する

まずは、データを渡すためにそのデータの構造を定義します。ここではinterfaceを使って型を定義します。

app.vue
interface Member {
  name: string;
  id: number;
  email: string;
  note?: string;
}

こんな感じでいいですかね。

それではapp.vueに追加しましょう。

app.vue
<script setup lang="ts">
interface Member {
  name: string;
  id: number;
  email: string;
  note?: string;
}
</script>

<template>
  <div>
    <UserCard />
    <UserCard />
  </div>
</template>

では、このMember型のインスタンスをつくっていきましょう。

app.vue
const memberListInit = new Map<number, Member>();
memberListInit.set(1, {
  id: 1,
  name: '田中太郎',
  email: 'taro.tanaka@example.com',
  note: 'ノートです。'
});
memberListInit.set(2, {
  id: 2,
  name: '鈴木次郎',
  email: 'suzuki.ziro@example.com'
});

こんな感じで大丈夫そうですね。

では、値が変わったらUIも自動で変わるようにするのに

app.vue
const memberList = ref(memberListInit);

refを実装しましょう。

それでは、一旦実装したものを出しますね。

app.vue
<script setup lang="ts">
interface Member {
  name: string;
  id: number;
  email: string;
  note?: string;
}

const memberListInit = new Map<number, Member>();
memberListInit.set(1, {
  id: 1,
  name: '田中太郎',
  email: 'taro.tanaka@example.com',
  note: 'ノートです。'
});
memberListInit.set(2, {
  id: 2,
  name: '鈴木次郎',
  email: 'suzuki.ziro@example.com'
});

const memberList = ref(memberListInit);
</script>

<template>
  <div>
    <UserCard />
    <UserCard />
  </div>
</template>

それでは次にPropsを送信していきましょう。
送信するにはv-bindを使います。そして、これは省略して:で書けるので

app.vue
<UserCard :name="member.name">

このように書くとPropsを送信することができます。

それでは実装していきましょう。
なお、app.vueの中でデータは二つ以上あるのでv-forも使いましょう。

app.vue
<template>
  <div>
    <UserCard
      v-for="[id, member] in memberList"
      :id="id"
      :key="id"
      :name="member.name"
      :email="member.email"
      :note="member.note"
    />
  </div>
</template>

これで子コンポーネントであるUserCardにPropsを送信することができました!

それではapp.vueの全体のソースコードを書いておきますね。

app.vue
<script setup lang="ts">
interface Member {
  name: string;
  id: number;
  email: string;
  note?: string;
}

const memberListInit = new Map<number, Member>();
memberListInit.set(1, {
  id: 1,
  name: '田中太郎',
  email: 'taro.tanaka@example.com',
  note: 'ノートです。'
});
memberListInit.set(2, {
  id: 2,
  name: '鈴木次郎',
  email: 'suzuki.ziro@example.com'
});
const memberList = ref(memberListInit);
</script>

<template>
  <div>
    <UserCard
      v-for="[id, member] in memberList"
      :id="id"
      :key="id"
      :name="member.name"
      :email="member.email"
      :note="member.note"
    />
  </div>
</template>

Propsを受け取る

次にUserCard.vueでPropsを受け取りましょう。

こっちでもapp.vueと同じようなinterfaceを用意しましょう。

components/UserCard.vue
interface Props {
  name: string;
  id: number;
  email: string;
  note?: string;
}

このとき、interfaceの中はv-bindで渡したときの属性名を指定してください。

そして、Propsを受け取りましょう。
受け取るにはdefineProps<Props>()を使います。

components/UserCard.vue
const props = defineProps<Props>();

この関数は、親コンポーネントでv-bindで送信されたPropsを受け取る関数です。

これでデータの受け取りができるようになりました!

次に受け取ったPropsを使っていきましょう。

といっても普通の変数のように埋め込めば大丈夫です。

components/UserCard.vue
<template>
  <div class="userCard">
    <h2> {{ props.name }} </h2>
    <p> ID: {{ props.id }} </p>
    <p> email: {{ props.email }} </p>
    <p> {{ props.note }} </p>
  </div>
</template>

これで表示されるのですが、props.nameのようにpropsを指定しなくてもnameだけでも表示することができるんです。
これは、defineProps関数を使うことによりこれができるようになるらしいです。

components/UserCard.vue
<template>
  <div class="userCard">
    <h2> {{ name }} </h2>
    <p> ID: {{ id }} </p>
    <p> email: {{ email }} </p>
    <p> {{ note }} </p>
  </div>
</template>

それでは最後に、Propsをスクリプトで制御してみましょう!

noteはinterfaceでオプショナルになっているので、この値がないときもあります。
そこで、データがないときに代わりの文字を表示するようにしてみましょう。

そのとき、スクリプト内では<template>のようにpropsを省略することはできませんので注意してください。

components/UserCard.vue
const localNote = computed<string>(() => {
  return props.note ?? '--';
});

こんな感じでよさそうですね。
ではこれを実装しましょう。

components/UserCard.vue
<template>
  <div class="userCard">
    <h2> {{ name }} </h2>
    <p> ID: {{ id }} </p>
    <p> email: {{ email }} </p>
    <p> {{ localNote }} </p>
  </div>
</template>

これで実装できました!

それでは最後にcomponents/UserCard.vueのソースコードを書いておきますね。

components/UserCard.vue
<script setup lang="ts">
interface Props {
  name: string;
  id: number;
  email: string;
  note?: string;
}

const props = defineProps<Props>();

const localNote = computed<string>(() => {
  return props.note ?? '--';
});
</script>

<template>
  <div class="userCard">
    <h2> {{ name }} </h2>
    <p> ID: {{ id }} </p>
    <p> email: {{ email }} </p>
    <p> {{ localNote }} </p>
  </div>
</template>

<style scoped>
.userCard {
  border: 1px solid green;
}
</style>

まとめ

今回は、Propsを使った親コンポーネントから子コンポーネントへのデータの受け渡しについて解説しました。

  • Propsは親から子にデータを渡すための仕組み。
  • 親コンポーネントではv-bindまたは省略形の:を使ってデータを送信。
  • 子コンポーネントではdefinePropsを使ってデータを受け取る。

次回は、EmitStateを使ったデータのやり取りについて解説する予定です。

それではお疲れさまでしたー🍎

GitHubで編集を提案

Discussion