1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

onMounted直後に処理を呼び出す方法

Last updated at Posted at 2024-09-04

まとめ

setTimeoutで処理をタイマー設定しておき、onMounted内での処理は全て終わったように見せることで対応した。

onMounted(() => {
    setTimeout(() => {
        isOpen.value = true; // ここにmounted直後に呼び出す処理を記述
    }, 0);
});

追記:コメントでアドバイスいただきました

1. queueMicrotask

マイクロタスク (microtask) とは、現在のタスクが完了し実行コンテキストの制御がブラウザーのイベントループへ戻る前、他に保留中のコードがなくなった時点で走る短い関数です。

現在のイベントループ内でのタスク完了後に自動で処理を走らせてくれる。
setTimeoutよりも軽量。

onMounted(() => {
    queueMicroTask(() => {
        isOpen.value = true; // ここにmounted直後に呼び出す処理を記述
    });
});

2. nextTick

onMounted(async () => {
    await nextTick();
    isOpen.value = true; // ここにmounted直後に呼び出す処理を記述
});

3. Promise.resolve

onMounted(async () => {
    await Promise.resolve();
    isOpen.value = true; // ここにmounted直後に呼び出す処理を記述
});

経緯

vuetifyのv-navigation-drawerを使用し動的に増えるドロワーを実装していた際、ドロワー表示アニメーションを呼び出そうとしていた。

親コンポーネント
<template>
    <SampleDrawer
        v-for="drawer in drawers" 
        :item="drawer.item"
        @open-new-drawer="openDrawer" 
        @close-drawer="closeDrawer">
    </SampleDrawer>
</template>
<script setup lang="ts">
    const drawers = ref<any[]>([]); // リストにドロワーを追加する度ドロワーが増える
</script>
Sample.vue
<v-navigation-drawer v-model="isOpen"></v-navigation-drawer>   

1. mounted時に呼び出し

create時にはfalseで、mounted時にtrueへ切り替えることによりアニメーションを表示させようとした。

isOpen = ref(false);

onMounted(() => {
    isOpen.value = true; // false状態で生成後、マウント時にtrueに変更
});

しかし、表示アニメーションはmounted時には呼び出されず更新時に呼び出される様で、結果としてアニメーション無しで表示されることとなってしまった。

2. mounted直後に呼び出し

そこで、mounted後に呼び出されるフックがあるかと思い(afterMount的な?)探したが残念ながら見つからず、下記の方法を試すこととした。

onMounted(() => {
    setTimeout(() => {
        isOpen.value = true; // onMounted自体はsetTimeoutの実行が完了した段階で完了し、
    }, 0);                   // onMounted完了直後にタイマー設定しておいたフラグ変更処理が走る
});

結果として無事アニメーションを表示することに成功した。

おまけ

ちなみに閉じるアニメーションについては分かりやすく、Unmountedでアニメーションが再生開始してから閉じるまで待った後に親からコンポーネントを削除する、といった形で解決した。

const closeDrawer = () => {
    setTimeout(() => {
        drawers.value.pop(); // アニメーション再生終了を待ってコンポーネント削除
    }, 500);
};

感想

明らかに外法な気がするので正しい方法があるならそちらを使いたい…

参考

1
0
2

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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?