TekRog
thumbnail

【Vue3】script setup構文の使用方法とメリット【propsとemitsも解説】

更新日:(作成日: )

カテゴリー:

シェア!

Vue3.2で<script setup>構文が導入され、Composition APIの記述が簡単になりました。<script setup>構文は記述が簡単になるだけでなく、他にも多くのメリットが存在します。この記事では<script setup>構文の説明から、propsやemitなどの特有の記述方法、メリットなどを説明します。

<script setup>構文の基本

記述方法

<script setup>構文は、従来のComposition APIのシンタックスシュガー(中身は同じで別の書き方)です。

Composition APIをご存じない方はこちらの記事を参照下さい。

<script setup>構文ですが、使うために必要なのはscriptタグ内ににsetupと記述するだけです。
まずは従来の記述方法と比較することで、具体的な記述方法を見ていきます。

・<script setup>構文

<script lang="ts" setup> import { computed, ref } from 'vue' //変数 const hoge = ref("hoge") const num = ref<number>() //関数 const onClick = () => console.log("clicked!") //computed const twice = computed(() => num.value) </script>

従来の方法

同じ内容のコードを従来通りに書くと次のようになります。

<script lang="ts"> import { defineComponent, ref, computed } from "vue"; export default defineComponent({ setup() { //変数 const hoge = ref("hoge") const num = ref<number>() //関数 const onClick = () => console.log("clicked!") //computed const twice = computed(() => num.value) return { hoge, num, onClick, twice } } }) </script>

見ての通り、最初に記載した<script setup>構文では圧倒的に記述が楽になりました。
また、全てトップレベルに記述できるのでコードの見通しも良いです。

具体的に言うと、次の3つの記述が不要になります。

  • export default defineComponentによるオブジェクトのラップ
  • setup()関数
  • return文

トップレベルに書いた変数や関数はがそのままtemplateで使えるのです。

メリット

記述が楽になりコードの見通しが良くなる、以外にも多くのメリットが存在します。
いくつか紹介します。

  • TypeScriptによる型推論のパフォーマンス向上!
  • PropとEmitの記述が楽に!TypeScriptで書ける(後述)
  • templateで使うコンポーネントは、importするだけで使用可能になる!(後述)
  • 実行パフォーマンスの向上!

<script setup>構文でのPropとEmitsの記述方法

基本〜definePropsとdefineEmits〜

従来のComposition APIでPropsとEmitは、setup()と同じ階層に併記していました。

<script setup>構文では、definePropsやdefineEmitsを用いて、トップレベルに記述します。

<script setup lang="ts"> const props = defineProps({ num: { type: Number, required: true }, str: { type: String, default: "hoge" } }) const emits = defineEmits( ['change'] ) </script>

typeやrequired、defaultの書き方は普通のsetup文の時と変わりません。

TypeScriptによる簡略化した記述

TypeScriptのジェネリックを使えば、更に簡単に記述できます。

<script setup lang="ts"> const props = defineProps<{ num: number, str?: string //?なのでrequired: falseと同じ }>() const emits = defineEmits<{ (e: 'change', id: number): void }>() </script>

以下、このコードについて解説します。

definePropsについて補足

コード例に載せたとおり、propsの型はTypeScriptの記述で指定します。
「num: number」はnumber型で必須(required: true)のpropsを表し、
「str?: string」はstring型で任意(required: false)のpropsにできます。

このように?の有無でrequiredの指定ができます。

ただし、この記述方法ではpropsのデフォルト値が表現できません。
デフォルト値が必要な場合はwithDefaults関数を利用します。

const props = withDefaults(defineProps<{ num?: number, str?: string }>(), { num: 3, str: "hoge" })

また、scriptブロック内でpropsは利用せずにtemplateブロック内でのみ利用する場合、const propsに代入せずに次のような宣言をするだけで構いません。

defineProps<{ msg: string }>()

defineEmitsについて補足

ジェネリックの<>内で必要な数のemitを定義していきます。
基本的な書き方は次のとおりです。

const emits = defineEmits<{ (e: "Emitの名前", 渡したい引数:): void (e: "Emitの名前2", 渡したい引数:): void }>()

具体的な使用例を載せます。

<script setup lang="ts"> const emits = defineEmits<{ (e: "hoge", num: number): void (e: "fuga"): void }>() const onclick = () => { emits("hoge", 3) //3を引数にhogeを発火 emits("fuga") //引数無しでfugaを発火 } </script>

コンポーネントは、importするだけで使用可能になる

templateで使うコンポーネントは、script setupブロック内でimportするだけで、template側で使用可能になります。

<script setup lang="ts"> import Child from './Child.vue'; </script> <template> <Child /> </template>

その他のトピック

親コンポーネントに変数を公開するには

親がテンプレート参照を用いて子トップレベルの変数等にアクセスするには、defineExposeを使う必要があります。

const num = ref<number>() defineExpose({ num })

これで、このコンポーネントを利用する親コンポーネントはテンプレート参照を用いてnumにアクセスできます。

exportするには

<script setup>構文ではexportの記述ができません。
従来の<script>だけの構文も記述してexportする必要があります。

<script lang="ts"> export const hoge = "fuga" //OK </script> <script setup lang="ts"> // export const fuga = "fuga" //エラー </script>

まとめ

<script setup>構文について、一通りの使い方とメリットを紹介しました。非常に多くのメリットが存在し、記述が簡単になり開発効率も上がるので積極的に利用すべきです。