ホームページ >ウェブフロントエンド >jsチュートリアル >Laravel、Inertia.js v、Vue 3 を使用した無限スクロールの実装

Laravel、Inertia.js v、Vue 3 を使用した無限スクロールの実装

Linda Hamilton
Linda Hamiltonオリジナル
2024-12-20 21:17:15259ブラウズ

Implementing Infinite Scrolling with Laravel, Inertia.js v, and Vue 3

この包括的なガイドでは、Inertia.js v2.0 と Vue 3 を使用して Laravel アプリケーションに無限スクロールを実装する方法を説明します。フロントエンドとバックエンドの両方について説明します。ページ全体の更新の処理とスクロール位置の維持に特に注意して実装します。

目次

  • コンポーネントを理解する
  • フロントエンドの実装
  • バックエンドの実装
  • 実際の例: カテゴリを含むブログ投稿
  • ベストプラクティスと考慮事項

コンポーネントを理解する

無限スクロールの実装は、次の 3 つの主要コンポーネントに依存しています。

  1. Inertia.js v2.0 の WhenVisible コンポーネント: このコンポーネントは、さらにコンテンツを読み込む必要がある時期を検出する交差オブザーバー ロジックを処理します。
  2. Laravel のページネーション: サーバー側のページネーション ロジックを処理します。
  3. Vue 3 のコンポジション API: フロントエンドの状態と反応性を管理します。

フロントエンドの実装

ブログ投稿リストの無限スクロールを実装する Vue コンポーネントから始めましょう。

<script setup>
import { computed } from 'vue'
import { usePage, WhenVisible } from '@inertiajs/vue3'
import LoadingSpinner from '@/components/LoadingSpinner.vue'
import BlogPostCard from '@/components/BlogPostCard.vue'

const page = usePage()

const hasFeaturePost = computed(() => !!page.props.featuredPost)
const categoryName = computed(() => page.props.category?.name)
</script>

<template>
    <div>



<h3>
  
  
  Key Frontend Features
</h3>

<ol>
<li><p><strong>WhenVisible Component</strong>: This component from Inertia.js v2.0 automatically triggers a request when the element becomes visible in the viewport.</p></li>
<li><p><strong>Pagination Parameters</strong>:<br>
</p></li>
</ol>

<pre class="brush:php;toolbar:false">:params="{
    data: {
        page: page.props.postsPagination.current_page + 1,
    },
    only: ['posts', 'postsPagination'],
}"
  • data: 次にロードするページを指定します
  • Only: 必要なデータのみを取得してリクエストを最適化します
  1. 読み込み状態: コンポーネントは、読み込み状態とコンテンツ終了状態の両方をエレガントに処理します。

バックエンドの実装

通常のページネーションと全ページ読み込みシナリオの両方を処理する Laravel コントローラーの実装は次のとおりです。

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Category;
use Illuminate\Pagination\LengthAwarePaginator;
use Inertia\Inertia;

class BlogController extends Controller
{
    public function index(?Category $category = null)
    {
        return Inertia::render('Blog/Index', [
            'category' => $category,
            'featuredPost' => $this->getFeaturedPost(),
            'posts' => $this->getPaginatedPosts($category),
            'postsPagination' => $this->getPaginatedPosts($category)?->toArray(),
        ]);
    }

    protected function getPaginatedPosts(?Category $category): ?LengthAwarePaginator
    {
        $currentPage = request()->input('page', 1);
        $perPage = request()->input('per_page', 12);

        $query = Post::query()
            ->with(['author', 'category'])
            ->published();

        if ($category) {
            $query->where('category_id', $category->id);
        }

        // Apply any additional filters
        if (request()->has('sort')) {
            $query->orderBy(request()->input('sort'), request()->input('direction', 'desc'));
        } else {
            $query->latest();
        }

        // Handle full page load vs. infinite scroll request
        if (!request()->header('X-Inertia')) {
            // Full page load - fetch all pages up to current
            $allResults = collect();

            for ($page = 1; $page <= $currentPage; $page++) {
                $pageResults = $query->paginate($perPage, ['*'], 'page', $page);
                $allResults = $allResults->concat($pageResults->items());
            }

            return new LengthAwarePaginator(
                $allResults,
                Post::query()
                    ->published()
                    ->when($category, fn($q) => $q->where('category_id', $category->id))
                    ->count(),
                $perPage,
                $currentPage
            );
        }

        return $query->paginate($perPage);
    }

    protected function getFeaturedPost()
    {
        return Post::query()
            ->with(['author', 'category'])
            ->published()
            ->featured()
            ->latest()
            ->first();
    }
}

主要なバックエンド機能

  1. ページネーションの処理:
if (!request()->header('X-Inertia')) {
    // Full page load logic
} else {
    // Regular pagination for infinite scroll
}
  1. 全ページ読み込み: ユーザーがページを更新するか直接アクセスすると、正しいスクロール位置を維持するために以前のページをすべてフェッチします。
for ($page = 1; $page <= $currentPage; $page++) {
    $pageResults = $query->paginate($perPage, ['*'], 'page', $page);
    $allResults = $allResults->concat($pageResults->items());
}
  1. 効率的なクエリ: この実装には、リレーションシップの積極的な読み込みとスコープ指定されたクエリが含まれています。
$query = Post::query()
    ->with(['author', 'category'])
    ->published();

結論

Laravel と Inertia.js v2.0 を使用して無限スクロールを実装すると、良好なパフォーマンスと SEO の実践を維持しながら、スムーズなユーザー エクスペリエンスが提供されます。 Vue 3 の Composition API と Inertia.js の WhenVisible コンポーネントを組み合わせることで、実装と保守が簡単になります。

次のことを忘れないでください:

  • 特にエッジケースについて、実装を徹底的にテストします
  • パフォーマンス指標を監視する
  • JavaScript が無効になっているユーザー向けにフォールバックの実装を検討してください
  • 無限スクロールを実装するときはアクセシビリティを念頭に置いてください

この実装は、製品リスト、画像ギャラリー、または無限スクロールの恩恵を受けるその他のコンテンツなど、ブログ投稿を超えたさまざまなユースケースに適応できます。

追加のリソース

  • Inertia.js ドキュメント
  • Laravel ドキュメント
  • Vue 3 ドキュメント
  • 無限スクロールに関する Web アクセシビリティ ガイドライン

以上がLaravel、Inertia.js v、Vue 3 を使用した無限スクロールの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。