Vue.js 3.2 からscript setup構文が使えるようになり、
単一ファイルコンポーネント(SFC)内で Composition API を使用している際に使える構文となります。
https://vuejs.org/api/sfc-script-setup.html
従来の Composition API における setup() 関数の内部の記述を、
純粋なJavaScript, TypeScriptのように、script直下に単純に変数や関数等を記述できます。
今回の記事ではscript setup構文における以下を簡潔に記載します。
- script setupの基本構文
- componentの読み込み
- component内のプロパティの公開方法
- Propsの書き方
- Emitの書き方
書き始める前に
VSCodeにおける.vue ファイルの拡張機能としてよく使われているVeturはscript setup構文には対応していません。
代わりに、Volarを使うことが推奨されています。
拡張機能を入れておきましょう。
https://marketplace.visualstudio.com/items?itemName=vue.volar
まずはscript setupの記述をする
<script setup lang="ts">
import { ref } from "vue";
const text = ref<string>('hello');
</script>
<template>
{{ text }}
</template>
従来のsetup()関数の記述の必要が無いため、非常にシンプルです。
textをバインドするためにreturnする必要もないため、従来の記法と比べて記述量が減ります。
Componentを読み込む
<script setup lang="ts">
import Child from "./components/Child.vue";
</script>
<template>
<Child />
</template>
componentsディレクトリ配下に作成したChild.vueをimportし、template内で呼び出す記述をするだけです。
Component内のプロパティを明示的に公開する
script setupを使用したコンポーネントは、デフォルトで閉じられています。
つまり、この状態ではテンプレート参照により、親から子コンポーネントの値にアクセスする事ができません。
そこで、コンポーネントのプロパティを明示的に公開するには、defineExposeコンパイラマクロを使用します。
script setupが処理されるときにコンパイルされます。
以下にChild.vueのchildMethodを明示的に公開した場合の記述をします。
- 親componentの記載
<script setup lang="ts">
const parentMethod = () => {
childRef.value.childMethod() // コンソールに1と出力される
};
</script>
<template>
<Child ref="childRef" />
<button @click="parentMethod">子コンポーネント内のchildMethodを実行する</button>
</template>
- 子componentの記載
<script setup lang="ts">
const a: number = 1;
const childMethod = () => {
console.log(a);
};
defineExpose({
childMethod
});
</script>
Propsを使う
propsを純粋なTypeScriptの構文で定義することができるようになりました。
script setupの中でpropsを宣言するには、definePropsのAPIを使用する必要があります。
definePropsは、script setup内でのみ使用可能なコンパイラマクロです。
- 親componentの記載
<script setup lang="ts">
import { ref } from "vue";
import Child from "./components/Child.vue";
const hello = ref<string>('hello');
</script>
<template>
<Child :text="hello" />
</template>
子側でこれから定義するtextに対してhelloを渡します。
- 子componentの記載
<script setup lang="ts">
import { ref } from "vue";
interface Props {
text: string;
}
const props = defineProps<Props>();
const text = ref<string>(props.text)
</script>
<template>
{{ text }} <!-- hello -->
</template>
props は defineProps() で定義されます。
interfaceで型定義をし、親側から渡ってきたhelloを使えるようにします。
Emitを使う
emitもpropsと同様に、TypeScriptにより型定義をすることが可能です。
script setupの中でemitを宣言するには、defineEmitsのAPIを使用する必要があります。
defineEmitsは、script setup内でのみ使用可能なコンパイラマクロです。
- 親componentの記載
<script setup lang="ts">
import Child from "./components/Child.vue";
const receiveText = (text: string) => {
console.log(text) // コンソールにhelloと出力される
}
</script>
<template>
<Child @emitText="receiveText" />
</template>
親側ではreceiveText関数を用意し、子から渡ってくるtextをconsole.logで見れるようにしておきます。
emitTextが発火するとreceiveTextが実行されます。
emitText発火時にtextが渡るように子側で定義すれば、receiveText内でtextを使うことができます。
それではemitTextはこれから子側で定義していきます。
- 子componentの記載
<script setup lang="ts">
interface Emits {
(e: "emitText", value: string): void;
}
const emit = defineEmits<Emits>();
const text: string = "hello"
const clickBtn = () => {
emit("emitText", text)
}
</script>
<template>
<button @click="clickBtn">ボタン</button>
</template>
上記の場合、ボタンをクリックすると、clickBtnが実行され、emitTextが発火し、textを親側へ渡します。
まとめ
まずはこの基本的な書き方ができれば、大方従来の書き方からscript setup構文に切り替える事はできるでしょう。
scirpt setup導入編として、少しでも参考にいただけますと幸いです。