beta

Vue.jsでトランジションの間にページがスクロールしちゃう問題

Vue.jsでSPAを開発していると、トランジションを使ってアプリっぽい挙動をつけたくなりますが、ページ遷移している間にページがスクロールしてしまう挙動が問題になることがあります。今回は、Vue.jsのスクロールの挙動をまとめました。

公開日:2019年8月23日

つけた動き

  • App.vueでrouter-viewをtransition
  • 一覧ページから詳細ページへ行く場合は、右へ遷移
  • 詳細ページから一覧ページへ戻る場合は、左へ遷移
  • 一覧ページはkeep-alive
  • scrollBehaviorで、savedPosition戻す

遭遇した問題点

  • トランジションの間に、遷移元のページが、遷移先のスクロールポジションにスクロールしてしまう

原因

色々試したところ、Vue.jsのトランジションは、

  • 遷移先のページをcreated、mounted
  • Router.jsでv-enterとv-leaveが発火
  • アニメーション
  • 遷移元をdestroy(keep-aliveならdeactivated)

という流れになっているようで、scrollBehaviorでsavedPositionに戻す設定を入れていると、どうしても遷移先のページをcreatedした段階で、スクロールが発生してしまい、遷移元のページが動いてしまいます。

流れで見ると、

  • 遷移元ページでトランジションを発火(ポジションは、{x:0, y: 600})
  • 遷移先をページをcreated(ポジションは、{x:0, y: 0})
  • ブラウザが{x:0, y: 0}にスクロール
  • スクロールしながら、Router.jsでv-enterとv-leaveが発火して、トランジションが実行
  • 遷移元をdestroy(keep-aliveならdeactivated)

という感じです。

ここをどうにかして画面遷移を設計しないといけません。

対策: トランジションモードでout-in、in-outを使う

vue-scroll-behaviorというプラグインを入れてみたり、アニメーションのタイミングをずらしてみたりと、色々と試してみましたが、これが一番効果がありました。

ただし、ページ遷移のアニメーションは移動してるというか、消えて表示される感じにはなってしまいますね。


Vue.jsでトランジションの間にページがスクロールしちゃう問題を見てきました。

単純なトランジションじゃなくて、コンポーネントを追加する感じとかにすればうまくできるのかもしれませんが、パフォーマンスとSEOを考えると無駄な情報は表示させたくありませんし、バランスが難しいですね。

とりあえずは、「トランジションモードでout-in、in-outを使う」で対策して、何か良い方法を見つけたらまたノートに書きたいと思います。