2022-03-26

Vue3 + TypeScript チートシートっぽいもの

目次

基本構成

<script setup lang="ts">
  ...
</script>

<template>
  ...
</template>

<style scoped>
  ...
</style>

リアクティビティ API

<script setup lang="ts">
import { ref, reactive, computed, toRefs } from "vue";
</script>

ref

const count = ref<number>(0);

reactive

interface State {
  name: string;
  age: number;
}
const state = reactive<State>({
  name: "yoshida",
  age: 36,
});

toRefs

ref を代入すると参照が切れてリアクティブ性が失われるので toRefs

const { name, age } = toRefs(state);

computed

const upperCaseName = computed(() => state.name.toUpperCase());

Template

変数参照

<template>
  <div>名前:{{ state.name }} | {{ upperCaseName }}
  <div>名前(toRef) {{ name }}
  <div>年齢:{{ state.age }}歳
  <div>年齢(toRef) {{ age }}
</template>

ディレクティブ

<template>
  <div>{{ count }}
  <button type="button" @click="count++">カウントアップ</button>
</template>

Props

<template>
  <Child label="propsLabel"/>
</template>

コンパイラマクロだから import は不要

<script setup lang="ts">
//型定義
interface Props {
  label: string;
}
//props
defineProps<Props>();
</script>

<template>
  <div>{{ label }}</div>
</template>

初期値を設定する場合

<script setup lang="ts">
//型定義
interface Props {
  label: string;
}
//初期値を設定
withDefaults(defineProps<Props>(), { label: "defaultLabel" });
</script>

Emit

const changeName = (value: string) => {
  state.name = value;
};
const updateName = (value: string) => {
  state.name = value;
};
  <Child @change="changeName" @update="updateName" label="propsLabel" />

//型定義
interface Emits {
  (event: "change", value: string): void;
  (event: "update", value: string): void;
}
//Emit
const emit = defineEmits<Emits>();
const handleUpdate = () => {
  emit("update", "update!");
};
<template>
  <input type="text" @input="handleInput" />
  <button type="button" @click="handleUpdate">アップデート</button>
</template>

Event

細かいことはおいておいて TypeScript で Event の扱いはややこしいのでとにかく使い方

instanceof で Type Guard

const handleInput = (e: Event) => {
  if (e.target instanceof HTMLInputElement) {
    emit("change", e.target?.value);
  }
};

as でキャスト

const handleInput = (event: Event) => {
  emit("change", (event.target as HTMLInputElement).value);
};