1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue3 Composition API のTSの書き方メモ

Last updated at Posted at 2024-09-05

2024-09-09
コメントでいただいた件を修正しました。

setupする

スクリプトタグにsetupを追加する

<script setup lang="ts">

defineXxxはimportに書かない

キホンの木

<script setup lang="ts">
defineProps({
  hoge: { type: String, default: "" }
});
const emit = defineEmits(['render']);
defineExpose({
  onClick: () => {}
});
// など

defineProps内の型の書き方

String, Number, Array, Object, Boolean以外の書き方

<script setup lang="ts">
import { PropType, withDefaults } from 'vue';

type Hoge { id: number };
interface Props {
  hoge?: Hoge;
  hoges?: Hoge[];
}
withDefaults(defineProps<Props>(), {
  hoge: undefined,
  hoges: () => []
});

reactiveな変数にはref or reactiveをつける

よく使う

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

const isOpen = ref(false);

const toggleOpen = () => {
  isOpen.value = !isOpen.value;
}

... 省略 ...

<template>
<!-- ここでは.valueは書かなくてOK --!>
<Modal :open="isOpen">

オブジェクトの場合はreactiveがラク

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

const statuses = reactive({ isOpenA: true, isOpenB: false });

const toggleOpenA = () => {
  statuses.isOpenA = !statuses.isOpenA;
}

refにコンポーネントを設定する 〜 親から子の関数を実行する

よく忘れるし、親コンポーネントから子コンポーネントの関数を叩くのはあまりない

Childコンポーネント
<script setup lang="ts">
import { ref } from 'vue';
import Hoge from './hoge.vue';

const hoge = ref<InstanceType<typeof Hoge> | null>(null);
const onClickHoge = () => {
  hoge?.value?.onClick?.();
}

... 省略 ...

<template>
<Hoge ref="hoge">
Parentコンポーネント
<script setup lang="ts">
defineExpose({
  onClick: () => {} // ←これが親から呼ばれる
})

refの余談

Vitestでテストを運用している + onMounted内でrefを更新している場合、
VitestがonMountedの更新を待たずにスナップショット撮るケースがあり、
以下で回避できる

import { nextTick } from 'vue';
import Hoge from './hoge.vue';

describe('ほげ', () => {
  it('ほげほげ', async () => {
    const wrapper = shallowMount(Hoge);
    await nextTick(); // onMountedが完了するのを待つ
    expect(wrapper.element).toMatchSnapshot();
  });
});

emitは$eventもしくは「...」で受け取る

呼び出し元のコンポーネントでご自由にどうぞ

Childコンポーネント
const emit = defineEmits(['open', 'close']);
const onOpen = () => {
  emit('open', true)
}
const onClose = () => {
  emit('close', true, false, 123)
}
Parentコンポーネント
const onClose = (...args) => {
  console.log(args); // [true, false, 123];
}

... 省略 ...

<template>
<Child @open="isOpen = $event" @close="onClose" />

更新可能なcomputedはgetter, setterを使う

emitとの連携がある場合にはすっきり書ける

const props = defineProps<{ isOpen: boolean }>();
const emit = defineEmits(['open'])
const open = computed({
  get: () => props.isOpen,
  set: (val) => emit('open', val),
});
1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?