🚴♀️
NuxtLinkのアニメーション実装時に、DOMExceptionが出た場合
一体何が起こったんだい?
Nuxt3で画面遷移時にアニメーションを設定した際、
アニメーションが終了する前に再び画面遷移しようとするとDOMExceptionが発生しました。
一度エラーが発生するとリロードしなければ詰んでしまうので、早急に対処せねばとなりました。
エラーメッセージは以下のようになっています。
結論
コミュニティ内で議論はされているものの、最善策は未だに見つかっていない模様
(というか、フレームワークのコアな部分なのでこちらからアプローチする方法がない?)
そういうわけで代替案ではあるものの、下記の実装がいいのかなとなりました。
- ユーザーがアニメーションを終了するまでルーティングできないようにする。
- エラーが発生した場合、リロードするイベントを作成する。
- 画面遷移時のアニメーションの実装は避ける。
実装(修正なし)
これといって特別なことはありませんが、下記のような実装となっています。
layout.vue
<template>
<div>
<NuxtLink :to="/">
Home
</NuxtLink>
<NuxtLink :to="/about">
About
</NuxtLink>
</div>
</template>
nuxt.config.ts
app: {
pageTransition: { name: "layout", mode: "out-in" },
}
app.vue
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<style>
.layout-enter-active,
.layout-leave-active {
transition: all 0.8s;
}
.layout-enter-from,
.layout-leave-to {
transform: translateX(800px);
opacity: 0;
}
</style>
実装(ルーティング防止修正)
指針
指針を元に改良
layout.vue
<script setup>
// アニメーション中か判定するフラグ
const isAnimation = ref(false);
// NuxtLinkをクリックした時の処理
const animationProcess = (linkPath) => {
// 既に表示している画面に対してのクリック -> 処理終了
if(linkPath === useRoute().fullPath) {
return;
}
// アニメーションフラグをtrueに
isAnimation.value = true;
// 2000ms後にfalseにするイベントを追加
window.setTimeout(() => {
isAnimaiton.value = (false);
}, 2000);
</script>
<template>
<div
class = {"event-none":isAnimation.value}
>
<NuxtLink
:to="/"
@click="animationProcess('/')"
>
Home
</NuxtLink>
<NuxtLink
:to="/about"
@click="animationProcess('/about')"
>
About
</NuxtLink>
</div>
</template>
<style>
.event-none {
pointer-events : none;
}
</style>
修正結果
クリックしようとしてもCSSでイベントを無くしているため、できないことがわかります。
手順
- NuxtLinkがクリックされた時にイベントが発生し、アニメーションフラグを立てる。
- NuxtLinkの親要素のdiv要素にクラスをバインドし、CSS「pointer-events:none」を動的に追加する。
- window.setTimeoutでイベントを作成し、n秒後に発火。
- 3で作成したイベントが発火することで、アニメーションフラグが落ちる。
注意点
まとめ
現状はごまかし程度でしか実装ができなかったので、
これからのアップデートで改善されることを期待しています。
(Vue開発者、コミュニティのみなさんには頭が上がらないです😇)
ここからは自身の話となりますが、
1年前にVueと出会いとても楽しいプログラミング生活をおくっています。
そのため技術力はよわよわですが、発信することで成長に繋げたいと思い今回執筆しました。
(間違ったことやもっといい方法があれば教えてください笑)
現在はSESとして業務システム関連を作っていますが、
いつかWebの世界で働けるように精進していきたいと思います!
拙い記事ですが、見てくださりありがとうございました!
Discussion