🐭

setup構文で書くVue.js

2022/06/18に公開

はじめに

初めまして。
今回、初めてこちらに記事を書かせていただきますWatatakuと申します。
よろしくお願いします。

<script setup>構文とは?

https://v3.ja.vuejs.org/api/sfc-script-setup.html#基本の構文
Vue.jsの3.2から使えるようになった記法です。

<script setup> は単一ファイルコンポーネント(SFC)内で Composition API を使用するコンパイル時のシンタックスシュガー(糖衣構文)です。SFC と Composition API の両方を使うならば、おすすめの構文です。

VSCode 拡張機能

VSCode における .vue ファイルの拡張機能としてVeturがよく使われていたかと思われますが、 <script setup> 構文には対応していません。
なので代わりに、Volarを使うことが推奨されています。

https://twitter.com/vuejs/status/1429195877365780486

基本の構文

<script setup>構文を解説する前に従来のVue.jsのコードを見ていきましょう。

  • Options API
<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    },
  },
});
</script>
  • Composition API
<template>
  <h1>{{ count }}</h1>
  <button @click="increment">Increment</button>
  <button @click="decrement">Decrement</button>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    const decrement = () => {
      count.value--;
    };
    return {
      count,
      increment,
      decrement,
    };
  },
});
</script>

簡単なカウンターアプリのコードです。
では、次に<script setup>構文です。

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);

const increment = () => {
  count.value++;
};

const decrement = () => {
  count.value--;
};
</script>

<template>
  <h1>{{ count }}</h1>
  <button @click="increment">Increment</button>
  <button @click="decrement">Decrement</button>
</template>

かなりシンプルになっています。

<script setup> 構文をざっくりと説明すると、従来の Composition API における setup() 関数内部を <script> 直下に直接記述することができるという構文です。


  • <script setup>構文ではexport default で Vue.js のオブジェクトを export する必要がなくなる
  • Composition API では、setup() 関数内で定義した変数や関数を return しないと <template> 内で使用することができなかったが、 <script setup>内で宣言した場合すべて使用可能となる

コンポーネント

今まで components に import したコンポーネントの一覧を登録しなければいけなかったのですが、import するだけで直接使えるようになりました。

  • 今まで
<template>
  <TheHeader />
  <main>main</main>
  <TheFooter />
</template>

<script lang="ts">
import TheHeader from "./components/TheHeader.vue";
import TheFooter from "./components/TheFooter.vue";

export default defineComponent({
  component: {
    TheHeader,
    TheFooter
  }
});
</script>
  • <script setup>構文
<script lang="ts" setup>
import TheHeader from "./components/TheHeader.vue";
import TheFooter from "./components/TheFooter.vue";
</script>

<template>
  <TheHeader />
  <main>main</main>
  <TheFooter />
</template>

propsとemit

props

<script setup>構文でpropsを扱うときはdefinePropsを使います。

<script setup lang="ts">
type Props {
  value: string;
  label?: string;
  type?: "text" | "password" | "email" | "number";
  placeholder?: string;
  disabled?: boolean;
}

defineProps<Props>();
</script>

<template>
  <label>
    {{ label }}
    <input
      :value="value"
      :type="type"
      :placeholder="placeholder"
      :disabled="disabled"
    />
  </label>
</template>

props のデフォルト値を定義する場合には、 withDefaults を使用します。

withDefaults(defineProps<Props>(), {
  label: "",
  type: "text",
  placeholder: "",
  disabled: false,
});

emit

<script setup>構文でemitを扱うときはdefineEmitsを使います。
emit も props と同様に、TypeScriptにより型定義をすることが可能です。

基本的な書式
type Emits = {
  (e: "Emitの名前", 渡したい引数:): void
  (e: "Emitの名前2", 渡したい引数:): void
}

defineEmits<Emits>();

では、具体的な扱い方です。

<script setup lang="ts">
type Emits {
  (e: "input", value: string): void;
  (e: "update:value", value: string): void;
}

defineEmits<Emits>();

const handleInput = ({ target }: { target: HTMLInputElement }) => {
  emit("input", target.value);
  emit("update:value", target.value);
};
</script>

<template>
  <label>
    {{ label }}
    <input
      :value="value"
      :type="type"
      :placeholder="placeholder"
      :disabled="disabled"
      @input="handleInput"
    />
  </label>
</template>

<script setup>構文のメリット

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

参考

https://vuejs.org/api/sfc-script-setup.html

https://tekrog.com/vue3-script-setup/

https://edge-labo.com/vue3-script-setup/

https://zenn.dev/azukiazusa/articles/676d88675e4e74

Discussion