【Vue.js】無限スクロールを実装する方法|Intersection Observerの活用

【Vue.js】無限スクロールを実装する方法|Intersection Observerの活用 Vue.js

Vue.jsでリスト表示を行う際、スクロールの位置に応じて次のデータを読み込む「無限スクロール(Infinite Scroll)」は、ユーザー体験を向上させる便利なUI手法です。従来はスクロールイベントを手動で監視する方法が一般的でしたが、Intersection Observer APIを使えば、より簡潔で高性能な実装が可能になります。本記事では、Vue 3とComposition APIで無限スクロールを実装する方法を解説します。

実装の概要

無限スクロールは以下のような流れで実装します:

  1. 表示用リストとデータ取得関数を用意
  2. リスト末尾に「監視用ダミー要素」を配置
  3. Intersection Observerでその要素の表示を検知
  4. 表示されたら次のデータを非同期で読み込む

Vueコンポーネントのサンプル実装

<template>
  <div class="post-list">
    <div v-for="post in posts" :key="post.id" class="post-item">
      {{ post.title }}
    </div>
    <div ref="loadTrigger" class="load-trigger">読み込み中...</div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const posts = ref([])
const page = ref(1)
const isLoading = ref(false)
const loadTrigger = ref(null)
let observer = null

const fetchPosts = async () => {
  if (isLoading.value) return
  isLoading.value = true

  const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_limit=10&_page=${page.value}`)
  const data = await response.json()

  posts.value.push(...data)
  page.value++
  isLoading.value = false
}

onMounted(() => {
  observer = new IntersectionObserver(
    (entries) => {
      if (entries[0].isIntersecting) {
        fetchPosts()
      }
    },
    {
      threshold: 1.0
    }
  )
  if (loadTrigger.value) {
    observer.observe(loadTrigger.value)
  }
})

onUnmounted(() => {
  if (observer && loadTrigger.value) {
    observer.unobserve(loadTrigger.value)
  }
})
</script>

<style scoped>
.post-list {
  max-width: 600px;
  margin: 0 auto;
}
.post-item {
  padding: 16px;
  border-bottom: 1px solid #ccc;
}
.load-trigger {
  padding: 16px;
  text-align: center;
  color: #888;
}
</style>

Intersection Observerの利点

  • スクロールイベントを使わないためパフォーマンスが高い
  • 監視対象のDOMが画面内に入ったかを自動検知
  • 複雑な計算やポーリングが不要

注意点とベストプラクティス

  • 読み込みが完了する前に複数リクエストを投げないようにisLoadingで制御
  • 全データを取得しきったら監視を停止(例:取得件数が0になったら)
  • 表示エリアが小さいとすぐに読み込みが連発することがあるため、初期表示件数を調整

まとめ

Vue.jsで無限スクロールを実装するには、Intersection Observerを使うのが最も効率的です。従来のスクロールイベントよりも可読性・保守性に優れ、パフォーマンス面でも有利です。表示するリストが大量になるアプリや、ユーザーがコンテンツをスムーズに閲覧できるUIを構築したいときに、ぜひ活用してみてください。