【学習記録⑳】Scroll Behavior関数を用いて遷移先の特定の項目へスクロールする。

# はじめに
Vue.jsを最近勉強し始めたので学んだ文法などを備忘録としてメモしていこうと思います。
今回は特定のページへ遷移後、指定された位置までスクロールする処理の実装について記載します。
通常、URLの後ろなどに`#example`等付けてリクエストを送ると、その要素を持つ位置まで自動でスクロールが走ります。
しかしながら`Vue Router`ではその機能が動かないように制御されており、実際にその機能を実現する際は専用の処理を書く必要があります。

## Scroll Behavior関数
特定のページへ遷移後、指定された位置までスクロールする処理を実装するためには`Scroll Behavior関数`を用いる必要があります。

https://next.router.vuejs.org/guide/advanced/scroll-behavior.html

使い方としては以下のようにルーティング設定を行っているファイル内で`scrollBehavior関数`を宣言し、専用の処理を書いていきます。

```js:router.js
const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            // ルーティング情報
        },
    ],
    scrollBehavior(to, from, savedPosition) {
        // 専用の処理を記載
    }
});
```

引数は`to`,`from`, `savedPosition`の3つを取り、それぞれ以下の意味合いを持ちます。

**to**
遷移先の情報

**from**
遷移元の情報

**savedPosition**
「戻る」などのボタンを押した際に遷移する前ページの位置情報

## 以上を用いてサンプルを作ってみる
それでは実際に`scrollBehavior関数`を用いて遷移先での自動スクロール機能を実装してみます。
内容としては「朝食ボタン」「詳細ボタン」があり、「朝食ボタン」をクリックすると遷移先の`写真を見る`部分へ自動スクロールされるものとします。

```js:router.js
import Morning from './views/Morning.vue';
import MorningDetails from './views/MorningDetails.vue';
import MorningBreakfast from './views/MorningBreakfast.vue';
import { createRouter, createWebHistory } from 'vue-router';

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/Morning',
            component: Morning,
            children: [
                {
                    path: 'details',
                    component: MorningDetails,
                    name: 'morning-details'
                },
                {
                    path: 'breakfast',
                    component: MorningBreakfast,
                    name: 'morning-breakfast'
                }
            ]
        },
    ],
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition)
            return savedPosition;
        // 遷移先のページにハッシュが付いていたら、対象の要素を持つ位置へスクロールします。
        // 今回は'smooth'というアニメーションを付けています。
        if (to.hash)
            return { el: to.hash, behavior: 'smooth' };

        // savedPosition, to.hashがともにない場合はスクロールは行われません。
        return { top: 0 };
    }
});

export default router;
```

```vue:App.vue
<template>
  <button @click="toBreakfast">朝食ボタン</button>
  <button @click="toDetails">詳細ボタン</button>
  <router-view></router-view>
</template>

<script>
export default {
  methods: {
    toBreakfast() {
      // 遷移先にて、スクロールしたい位置の要素を'hash'オプションへ追加します。
      this.$router.push({ name: "morning-breakfast", hash: '#LookPicture' });
    },
    toDetails() {
      this.$router.push({ name: "morning-details" });
    }
  },
};
</script>
```

```vue:Morning.vue
<template>
  <div>おはよう</div>
  <router-view></router-view>
</template>
```

```vue:MorningBreakfast.vue
<template>
  <div>朝ごはんはパンです。</div>
  <div style="height: 1000px;"></div>
  <!-- ↓遷移後、スクロール先の項目へid要素を付与しています。 -->
  <router-link id="LookPicture" to="/Morning">写真を見る</router-link>
  <div style="height: 1000px;"></div>
</template>
```

```vue:MorningDetails.vue
<template>
  <div>だんだん冷えてきたので体調には気を付けていきましょう。</div>
</template>
```

## 結果
以下のようにページ遷移後、指定した要素へスクロールされていることが分かります。
![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/10da62dc-0ca8-12c6-212a-326c3aa0928b.gif)

# おわりに
今回は`Scroll Behavior関数`を用いて遷移先の特定の項目へスクロールする処理の実装を行いました。
自前で実装しないといけないとはいえ、元の関数は用意してくれているので比較的楽に実装できて良い感じです！