LoginSignup
3
8

More than 5 years have passed since last update.

Vuetifyのタブコンポーネントで各タブごとにスクロール位置を保持する

Last updated at Posted at 2018-06-12

Vuetifyのタブコンポーネント

VuetifyはVue.jsに対応したUIコンポーネントライブラリです。今回はこの中のタブ(v-tabs)に関するTipsです。
https://vuetifyjs.com/ja/components/tabs

タブごとにスクロール位置を保持したい

例えば、3つのタブを作り、その中にInstagramのタイムラインのようなコンテンツのリストを表示するとします。
このとき、次のような事象が発生します。

  1. タブAでwindow.scrollYが500になるまでスクロール
  2. タブBに切り替え
  3. タブBでもスクロール位置(window.scrollY)が500になっている

感覚的には、タブAでwindow.scrollY=500の位置までスクロールしても、タブBに切り替えたときには一番上(window.scrollY=0)の位置を表示してほしいですよね。

方針

次のような方針で対応していきます。

  • スクロールのイベントハンドラを追加する
  • スクロールが発生したら、現在表示中のスクロール位置を保持する(タブごとに別々に保持)
  • v-tabsv-modelに指定したプロパティ(例: active)をwatchする
  • activeの変更を検知したタイミングで、保持しておいたスクロール位置に変更する

実装

Javascriptの処理はこんな感じ。

sample.vue
<script>
export default {
    data() {
        active: 'tabA', // アクティブなタブ名
        // 各タブのスクロール位置
        position: {
            tabA: null,
            tabB: null,
            tabC: null,
        },
    },
    mounted() {
        // イベントリスナの追加
        window.addEventListener('scroll', this.handleScroll);
    },
    destroyed() {
        // イベントリスナの削除
        window.removeEventListener('scroll', this.handleScroll);
    },
    methods: {
        handleScroll() {
            // 現在アクティブなタブのスクロール位置を保持
            this.position[this.active] = window.scrollY;
        }
    },
    watch: {
        // activeの変更を検知
        active() {
            // 切り替え後のタブですでに保持されたスクロール位置があればその位置を取得
            const y = this.position[this.active] || 0; 

            // 即時スクロールすると、切り替え前のタブの長さ < 切り替え後のタブの長さである場合に、切り替え前のタブの最大値までしかスクロールされないことがある(切り替え後のタブの内容が描画される前にスクロールしようとする)ので、setTimeoutでタイミングを少しずらす
            setTimeout(() => {
                window.scroll(0, y);
            }, 200);
        },
    },
};
</script>

終わりに

省略した<template>の部分は基本的にVuetifyのサンプルを見てもらえばと思いますが、要望がありましたら追記します。

3
8
0

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
3
8