お問い合わせ

ブログ

これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。

Vue3のSFC(single file component)で<script setup>を使って楽をする

okuda Okuda 2 years

<script setup> は単一ファイルコンポーネント(SFC)内で Composition API を使用するコンパイル時のシンタックスシュガー。

<script> の代わりに <script setup> を使用することで setup() 関数の内容としてコンパイルされるので setup() を省略できる。

setup内でreturnしなくてもトップレベルのものは<template>内で使用できる。

今までとは<template><script>の順序が入れ替わり、 <template><script><style>の順になる
これはコーディングルール的なもの。

コンポーネントにはパスカルケースを推奨。

メリットとしては

  • お決まりのパターンを減らし簡潔に書ける
  • propsemit の定義に TypeScript の構文が使える
  • ランタイムのパフォーマンスが向上
  • IDE のパフォーマンスが向上

vscodeの拡張機能は「Vetur」から「Volar」に変更する

トップレベルのバインディング(変数、関数、インポート)

<script setup> 内で宣言されたトップレベルのバインディング(変数、関数、インポート)は、テンプレートで直接使用できる。

<script setup> 内でインポートされたカスタムコンポネントはタグ名として直接使用できる。

<script setup>
// 変数
const msg = 'Hello!'

// 関数 関数を宣言するだけでテンプレート内で使用可能
function log() {
  console.log(msg)
}

//インポート `capitalize` はテンプレート内で使用可能
import { capitalize } from './helpers'

// カスタムコンポネント
import MyComponent from './MyComponent.vue'
</>

<template>
  <!-- 変数と関数 -->
  <div @click="log">{{ msg }}</div>
  <!-- インポートした関数 -->
  <div>{{ capitalize('hello') }}</div>
  <!-- インポートしたカスタムコンポネント -->
  <MyComponent />
</template>

リアクティビティ

refreactivecomputedなどはそのまま

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

const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

コンポーネント

<script setup>内で動的コンポーネントを使う場合は、コロンをつけた:is バインディングを使う必要がある。

SFCはファイル名で暗黙的に参照するので、FooBar.vue というファイル名は、テンプレート内で として参照できる。

名前と競合する名前付きインポートがある場合、インポートでエイリアスを作成する。

<script setup>
// 動的にコンポネントを使用する
import Foo from './Foo.vue'
import Bar from './Bar.vue'
// 変数
const someCondition = true

// 暗黙的名前空間付きコンポーネント
// import Bar from './Bar.vue'
import { Baz as Baz2 } from './your/Baz.vue'
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />

  <!-- Baz.vue -->
  <Baz />
  <Baz2 />
</template>

名前付きコンポネント (ネスティッド コンポネント)

<form.Bar> のようにドット付きのコンポーネントタグを使って、オブジェクトプロパティの下にネストしたコンポーネントを参照することができる。

components/Forms/Input.vue
Formsにネストされるコンポネント

<template>
  <input type="text" />
</template>

components/Forms/Checkbox.vue
Formsにネストされるコンポネント

<template>
  <input type="text" />
</template>

components/Forms.js
このファイルでまとめる

export { default as Input } from "./components/Forms/Input.vue";
export { default as Checkbox } from "./components/Forms/Checkbox.vue";

App.vue
使用するとき

<script lang="ts" setup>
import * as Form from "./components/Forms";
</script>

<template>
  <Form.Input />
  <Form.Checkbox />
</template>

props と emits

<script setup> の中で propsemits を宣言するには definePropsdefineEmits を使用する。
インポートする必要なし。

<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
</script>

useSlots と useAttrs

useSlots() と useAttrs() を使用。

<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

defineExpose

<script setup> コンポーネントのプロパティを明示的にテンプレート内に公開する場合は defineExpose を使用する。

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

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>

トップレベルの await

<Suspense>で待機対象となるので必ず<Suspense>と組み合わせて使用しなくてはならない。

<script setup>
const {data, status} = await axios.get(`http://api.comc`)
</script>

<template>

  <suspense>
    <template #default>{{data}}</template>
    <template #fallback>Loading...</template>
  </suspense>

</template>

純粋にawaitしたい場合は、以下のような方法がある。

<script setup>
import { onBeforeMount } from "vue";

onBeforeMount(async () => {
  const { status, data } = await axios.get(`http://api.comc`)
});
Vue3のSFC(single file component)で<script setup>を使って楽をする 2022-02-16 16:45:15

コメントはありません。

4241

お気軽に
お問い合わせください。

お問い合わせ
gomibako@aska-ltd.jp