Nuxt3でページ遷移時にページトップにスクロールする

code on a screen NuxtJS
Photo by Markus Spiske on Pexels.com
この記事は約5分で読めます。

Nuxt3でページ遷移時にページトップにスクロールさせる方法についてです。

ふと、rc.13版にアップグレードしてみるとスクロールトップのオプションが入っているようでした。Transitionのfinishのタイミングでページトップにスクロールされるのがデフォルトの動作のようです。
https://github.com/nuxt/framework/pull/3851

環境

  • nuxt@3.0.0-rc.13
  • Node.js v16.18.0

サンプルアプリの構成は以下のとおりです。

$ tree -I 'node_modules'
.
├── README.md
├── app
│   └── router.options.ts
├── app.vue
├── layouts
│   └── default.vue
├── nuxt.config.ts
├── package-lock.json
├── package.json
├── pages
│   ├── index.vue
│   └── other-page.vue
├── plugins
│   └── scrolltop.client.ts
└── tsconfig.json

4 directories, 11 files
 本記事作成時、Nuxt3はまだベータリリースのため動作が変わる可能性もあります。

ページ遷移時にスクロールする

page:finishのフックを使って、scrollTo関数でページトップにスクロールさせます。

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook("page:finish", () => {
     window.scrollTo({ left: 0, top: 0 });
  });
});

Transition後にスクロールする

ページコンポーネントのdefinePageMeta及びapp/router.optionsで指定する方法があります。nuxt.config.tsrouter.optionsではJSONでserializeされるオプションのみ指定が可能なようです。それぞれ見ていきます。

definePageMeta

definePageMetascrollTopというプロパティがあります。デフォルトは、trueになっているので、ページ遷移のtransition後にページトップにスクロールされます(page:transition:finishフックが呼ばれる)。スクロールを無効にする場合は、falseにすればよさそうです。

<script lang="ts" setup>
definePageMeta({
  pageTransition: {
    name: "fade",
    mode: "out-in",
    appear: true,
    duration: 1000,
  },
});
</script>

<template>
  <div>
    <div class="box">
      <h1>Index Page</h1>
    </div>
    <NuxtLink to="/other-page">別ページ</NuxtLink>
  </div>
</template>

<style>
.box {
  height: 1000px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
<script lang="ts" setup>
definePageMeta({
  pageTransition: {
    name: "fade",
    mode: "out-in",
    appear: true,
    duration: 1000,
  },
  scrollToTop: false, // スクロールさせない
});
</script>
<template>
  <div>
    <div class="box">
      <h1>Other Page</h1>
    </div>
    <NuxtLink to="/">ホームページ</NuxtLink>
  </div>
</template>

<style>
.box {
  height: 1000px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>

app/router.options.ts

vue-routerのscrollBehaviorを独自に実装します。

import type { RouterConfig } from "@nuxt/schema";

// https://router.vuejs.org/api/interfaces/routeroptions.html
export default <RouterConfig>{
  scrollBehavior(to, from, savedPosition) {
    return { left: 0, top: 0 };
  },
};

参考リンク

コメント

タイトルとURLをコピーしました