Giới thiệu

Laravel Livewire cho phép xây dựng giao diện động mà không cần viết JavaScript. Khi dữ liệu tăng lên, việc tải toàn bộ bản ghi sẽ gây chậm trễ và tiêu tốn tài nguyên. Bài viết này sẽ hướng dẫn cách kết hợp paginationlazy loading trong Livewire để tối ưu hiệu suất và trải nghiệm người dùng.

Triển khai Pagination trong Livewire

Livewire cung cấp trait WithPagination giúp thực hiện phân trang một cách nhanh chóng. Dưới đây là một component cơ bản sử dụng trait này.

<?php
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Post;

class PostList extends Component
{
    use WithPagination;

    public $search = '';

    public function updatingSearch()
    {
        $this->resetPage();
    }

    public function render()
    {
        $posts = Post::where('title', 'like', "%{$this->search}%")
                     ->orderByDesc('created_at')
                     ->paginate(10);
        return view('livewire.post-list', ['posts' => $posts]);
    }
}
?>

Trong phương thức render(), chúng ta truy vấn Post với điều kiện tìm kiếm và áp dụng paginate(10) để lấy 10 bản ghi mỗi trang. Khi người dùng thay đổi từ khóa tìm kiếm, phương thức updatingSearch sẽ reset lại trang hiện tại để tránh lỗi trang trống.

Thêm tính năng tìm kiếm

Để cho phép người dùng nhập từ khóa, chúng ta thêm một input trong view:

<div>
    <input type="text" wire:model.debounce.500ms="search" placeholder="Tìm tiêu đề..." />
    <ul>
        <?php foreach($posts as $post): ?>
            <li><?= $post->title ?></li>
        <?php endforeach; ?>
    </ul>
    <div>
        {{ $posts->links() }}
    </div>
</div>

Thuộc tính wire:model.debounce.500ms giúp giảm số lần gửi request khi người dùng gõ liên tục, nhờ đó giảm tải cho server.

Áp dụng Lazy Loading cho các phần phụ

Trong một danh sách bài viết, chúng ta thường muốn tải ảnh hoặc nội dung chi tiết chỉ khi người dùng cuộn tới. Livewire hỗ trợ lazy thông qua wire:loadingwire:target. Dưới đây là ví dụ tải ảnh thumbnail một cách lazy.

<div>
    <?php foreach($posts as $post): ?>
        <div wire:ignore>
            <img src="{{ $post->thumbnail }}" alt="{{ $post->title }}" loading="lazy" />
            <h3>{{ $post->title }}</h3>
        </div>
    <?php endforeach; ?>
</div>

Thuộc tính loading="lazy" của thẻ img được hỗ trợ bởi trình duyệt hiện đại, giúp trì hoãn việc tải ảnh cho tới khi chúng xuất hiện trong viewport.

Tối ưu truy vấn và cache

Đối với các trang có lượng truy vấn lớn, việc cache kết quả phân trang là một cách hiệu quả. Laravel cung cấp Cache::remember để lưu trữ kết quả trong một khoảng thời gian nhất định.

<?php
use Illuminate\Support\Facades\Cache;

public function render()
{
    $posts = Cache::remember('posts-page-'.$this->page, 60, function() {
        return Post::where('title', 'like', "%{$this->search}%")
                   ->orderByDesc('created_at')
                   ->paginate(10);
    });
    return view('livewire.post-list', ['posts' => $posts]);
}
?>

Cache sẽ giảm tải cho database khi người dùng truy cập lại các trang đã xem trong vòng 60 giây.

Kết luận

Việc kết hợp pagination, debounce tìm kiếm, lazy loading ảnh và cache truy vấn sẽ giúp ứng dụng Laravel Livewire của bạn phản hồi nhanh hơn và tiêu thụ ít tài nguyên hơn. Để nắm vững toàn bộ quy trình và các kỹ thuật nâng cao, bạn có thể Tham khảo khóa học "Khóa học Laravel Livewire từ cơ bản đến nâng cao" tại đây.