Skip to content

Vue 3のscript setupでのpropsの使い方

Vue 3のComposition APIと<script setup>構文を使用すると、コンポーネントの記述がより簡潔になります。この記事では、<script setup>でpropsを正しく定義し使用する方法について詳しく解説します。

問題点

元のコードでは、definePropsでpropsを定義していますが、非同期関数内でpropsにアクセスする方法がわからないという問題がありました:

vue
<script setup>
import { defineProps, reactive } from 'vue'

defineProps({
  no: String
})

const init = async () => {
  // props.no にどうやってアクセスする?
  // const { data } = await getRoomByNo(props.no)
}
init()
</script>

基本的なpropsの定義方法

<script setup>では、defineProps関数を使用してpropsを定義します。これはコンパイル時のマクロであり、明示的なインポートは不要です。

vue
<script setup>
const props = defineProps({
  no: String,
  isOpen: Boolean,
  count: Number
})

console.log(props.no) // propsの値にアクセス
</script>

リアクティブなpropsの使用方法

propsをリアクティブに扱いたい場合、toRefsを使用して分割代入することが推奨されます:

vue
<script setup>
import { toRefs } from 'vue'

const props = defineProps({
  no: String,
  myId: Number
})

// リアクティブを保つためにtoRefsを使用
const { no, myId } = toRefs(props)

console.log(no.value) // .valueで値にアクセス
console.log(myId.value)
</script>

TypeScriptを使用した型定義

TypeScriptを使用する場合、より厳密な型チェックが可能です。

インターフェースを使用した方法

vue
<script setup lang="ts">
interface Props {
  disabled: boolean
  loading: boolean
  bordered: boolean
  label?: string
}

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

リテラル型を使用した方法

vue
<script setup lang="ts">
type Color = 'primary' | 'info' | 'success' | 'error' | 'warning'

const props = defineProps<{
  color: Color
  size: 'small' | 'medium' | 'large'
}>()
</script>

デフォルト値の設定

JavaScriptの場合

vue
<script setup>
defineProps({
  isOpen: {
    type: Boolean,
    default: true
  },
  label: {
    type: String,
    default: 'Default Label'
  }
})
</script>

TypeScriptの場合

vue
<script setup lang="ts">
interface Props {
  msg?: string
  count?: number
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  count: 0
})
</script>

実際の使用例

以下は、propsを受け取るコンポーネントの完全な例です:

vue
<template>
  <div class="px-4 w-8/12 sm:w-3/12">
    <img :src="src" :alt="alt" class="border-none rounded-full h-auto max-w-full align-middle" />
  </div>
</template>

<script setup>
const props = defineProps({
  src: String,
  alt: String,
})
</script>
vue
<template>
  <div class="flex flex-wrap justify-center">
    <CircleImage src="/file1.jpg" alt="one" />
    <CircleImage src="/file2.svg" alt="two" />
  </div>
</template>

<script setup>
import CircleImage from '@/components/CircleImage.vue'
</script>

注意点

WARNING

propsは読み取り専用です。子コンポーネント内でpropsを変更しようとしないでください。代わりに、親コンポーネントにイベントを発行して状態の変更を要求しましょう。

TIP

definePropsはコンパイル時マクロであり、実行時には存在しません。JavaScript/TypeScriptの式の中で動的にpropsを定義することはできません。

まとめ

Vue 3の<script setup>構文では、definePropsを使用してpropsを定義します。TypeScriptを使用する場合は型安全性を高め、必要に応じてwithDefaultsでデフォルト値を設定します。propsをリアクティブに扱う場合はtoRefsを使用して分割代入することで、コンポーネントの可読性と保守性を高めることができます。

これらのテクニックを活用することで、より明確で型安全なVueコンポーネントを作成することが可能になります。