• Час читання ~2 хв
  • 14.03.2023

У цьому підручнику ми реалізуємо Livewire Infinite Scrolling, яка автоматично завантажуватиме записи з бази даних, коли користувач прокручується внизу списку. І на відміну від інших прикладів, які ви могли бачити, ми переконаємося, що наш код є ефективним, і не отримаємо всі записи під час повторного відтворення компонента.

Preview

Я починаю з проекту Fresh Laravel зі встановленим Livewire. Я також встановив Breeze, але це не обов'язково і повністю залежить від вас. Я також створив маршрут, де ми збираємося відображати наш компонент Livewire. І, нарешті, у мене є модель продукту, яку я засіяв кількома записами. Ми будемо прокручувати список продуктів.

Ми можемо створити компонент Livewire, використовуючи наведену нижче команду Artisan.

php artisan make:livewire LoadProducts

Ми можемо відтворити його в нашому поданні за допомогою наведеної нижче команди

@livewire('load-products')

І в рамках цього компонента Livewire я збираюся визначити 2 властивості, $page і $perPage. Я збираюся встановити ці властивості в методі кріплення.

<?php

namespace App\Http\Livewire;

use App\Models\Product;
use Livewire\Component;

class LoadProducts extends Component
{
    public $perPage;
    public $page;

    public function mount($page = null, $perPage = null) 
    {
        $this->page = $page ?? 1;
        $this->perPage = $perPage ?? 10;
    }
}

Оскільки ми не надали жодних значень під час візуалізації компонента Livewire, і $perPage матимемо $page значення за замовчуванням 1 та 10 відповідно.

Далі ми збираємося створити метод візуалізації, який поверне записи, що відповідають 1-й сторінці, і передасть їх до нашого переглядуload-products

public function render()
    {
        $products = Product::paginate($this->perPage, ['*'], null, $this->page);
        return view('livewire.products.load-products', [
            'products' => $products
        ]);
    }

У нашому поданні файлу, який знаходиться за адресою resources/views/livewire/products/load-products.blade.php , ми можемо просто циклічно переглядати всі Продукти.

<div>
    @foreach($productsas $result)
       .
       . 
       .
    @endforeach
</div>

На цьому етапі, якщо ви відкриєте свій маршрут, що містить цей компонент Livewire, ви побачите перші 10 записів.

Перш за все, ми будемо використовувати кнопку для завантаження більшої кількості записів. Як тільки ми це запрацюємо, ми перейдемо до прокрутки.

Тепер ми можемо додати кнопку після того, як наш foreach цикл закінчиться, як нижче

<x-button wire:click="loadMore">Load More Products</x-button>

Одним натисканням цієї кнопки нам потрібно отримати наступні 10 записів і додати до поточного списку. Однак Livewire візуалізує весь компонент, щоб ми могли використовувати підхід додавання.

Другий варіант полягає в тому, щоб отримати всі 20 записів і знову відтворити компонент. Це створить ілюзію завантаження більшої кількості даних, але воно має серйозні проблеми з продуктивністю.

Натомість ми збираємося створити ще один компонент, LoadMoreProducts. Цей компонент відповідатиме за:

  1. Відображення наведеної вище кнопки «Завантажити більше продуктів».
  2. Обробка події Click, яка отримає Продукти для 2-ї та наступних сторінок.
  3. Умовне відображення подання, пов'язаного з LoadProducts Компонент.

Таким чином, ми можемо створити цей компонент за допомогою команди нижче:

php artisan make:livewire LoadMoreProducts

Ми додамо цей компонент у наш файл перегляду, як показано resources/views/livewire/products/load-products.blade.php нижче:

@if($products->hasMorePages())
        @livewire('load-more-products', ['page' => $page, 'perPage' => $perPage, 'key' => 'products-page-' . $page])
    @endif

Будь ласка, переконайтеся, що ми відображаємо цей компонент, лише якщо є більше Продуктів, які потрібно отримати. Ми також передаємо $page і $perPage Майно. Ми також використовуємо унікальний ключ для його ідентифікації, оскільки цих компонентів буде кілька, по 1 для кожної наступної сторінки.

У нашому файлі компонентів, розташованому за адресою app/Http/Livewire/LoadMoreProducts, ми матимемо наступний код, який на даному етапі дуже схожий на LoadProducts

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Product;

class LoadMoreProducts extends Component
{

    public $perPage;
    public $page;
    public $loadMore = false;

    public function mount($page = null, $perPage = null) 
    {
        $this->page = $page ?? 1;
        $this->perPage = $perPage ?? 10;
    }

    public function render()
    {
        return view('livewire.products.load-more-products');
    }
}

У файлі перегляду цього компонента, розташованого за адресою resources/views/livewire/products/load-more-products.blade.php, ми в кінцевому підсумку відобразимо нашу кнопку.

<x-button wire:click="loadMore">Load More Products</x-button>

Як бачите, ми викликаємо loadMore метод одним натисканням цієї кнопки. Нам потрібно визначити цей метод у LoadMoreProducts компоненті, і він буде обробляти такі функції:

  1. Ми збільшимо $page властивість на 1.
  2. Ми визначимо новий прапор loadMore і встановимо його на істинний.
  3. В рамках методу візуалізації ми перевіримо вищевказаний прапорець. Якщо цей прапорець відповідає дійсності, ми отримаємо записи з БД для заданого та $page відобразимо подання, пов'язане з LoadProducts компонентом. В іншому випадку ми просто відобразимо вигляд, пов'язаний з LoadMoreProducts, який візуалізує кнопку.

Ось як виглядає наш компонент LoadMoreProducts

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Product;

class LoadMoreProducts extends Component
{

    public $perPage;
    public $page;
    public $loadMore = false;

    public function mount($page = null, $perPage = null) 
    {
        $this->page = $page ?? 1;
        $this->perPage = $perPage ?? 10;
    }

    public function loadMore() 
    {
        $this->page += 1;
        $this->loadMore = true;
    }

    public function render()
    {
        if (!$this->loadMore) {
            return view('livewire.products.load-more-products');
        } else {
            $products = Product::paginate($this->perPage, ['*'], null, $this->page);

            return view('livewire.products.load-products', [
                'products' => $products
            ]);
        }
    }
}

Тому, коли Користувач запитує 2-гу сторінку, ми отримуємо Продукти, пов'язані з 2-ю сторінкою, і відображаємо їх через livewire.products.load-products. Потім у цьому поданні також відображається кнопка «Завантажити більше продуктів» для 3-ї сторінки.

Таким чином, розбивши функціональність на два компоненти, ми вирішили проблему додавання до поточного списку.

Тепер давайте внесемо зміни, щоб завантажити більше Продуктів, коли користувач прокручує, а не натискає кнопку. Нам потрібно лише внести зміни в Вид LoadMoreProducts. Нам потрібно запустити подію кліків, коли користувач прокручує до кінця списку. Ми можемо зробити це, скориставшись x-init Директивою Альпійських Дж.

<div x-data="{
    checkScroll() {
            window.onscroll = function(ev) {
                if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
                     @this.call('loadMore')
                }
            };
        }
    }"

    x-init="checkScroll"
>

Тепер, коли користувач прокручується до кінця списку, метод буде запущено, loadMore а записи будуть додані в кінець списку. Ми отримаємо той же висновок, що показано на зображенні на початку підручника.

Якщо вас зацікавив код, ви можете отримати його з Github.

Сподіваюся, вам сподобався цей підручник. За подібними статтями ви можете підписатися на мене в Twitter

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297