W tym samouczku zaimplementujemy Livewire Infinite Scrolling, który automatycznie załaduje rekordy z bazy danych, gdy użytkownik przewinie do dołu listy. W przeciwieństwie do innych przykładów, które mogłeś zobaczyć, upewnimy się, że nasz kod jest wydajny i nie pobiera wszystkich rekordów podczas ponownego renderowania komponentu.
Zaczynam od Fresh Laravel Project z zainstalowanym Livewire. Zainstalowałem również Breeze, ale nie jest to obowiązkowe i całkowicie zależy od ciebie. Ustawiłem również trasę, na której będziemy wyświetlać nasz komponent Livewire. I wreszcie, mam Model Produktu, który zasiałem kilkoma rekordami. Będziemy przewijać listę Produktów.
Możemy utworzyć komponent Livewire za pomocą poniższego polecenia Artisan.
php artisan make:livewire LoadProducts
Możemy wyrenderować go w naszym widoku za pomocą poniższego polecenia
@livewire('load-products')
W ramach tego komponentu Livewire zdefiniuję 2 właściwości $page
i $perPage
. Zamierzam ustawić te właściwości w metodzie mount.
<?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;
}
}
Ponieważ nie podaliśmy żadnych wartości podczas renderowania komponentu $page
Livewire i będziemy mieli wartość domyślną odpowiednio 1 i $perPage
10.
Następnie utworzymy metodę renderowania, która zwróci rekordy odpowiadające 1st Page i przekaże ją do naszego View load-products
public function render()
{
$products = Product::paginate($this->perPage, ['*'], null, $this->page);
return view('livewire.products.load-products', [
'products' => $products
]);
}
W naszym pliku widoku, który znajduje się pod adresem resources/views/livewire/products/load-products.blade.php
, możemy po prostu zapętlić wszystkie produkty.
<div>
@foreach($productsas $result)
.
.
.
@endforeach
</div>
Na tym etapie, jeśli otworzysz trasę zawierającą ten komponent Livewire, zobaczysz pierwszych 10 rekordów.
Przede wszystkim użyjemy przycisku do załadowania większej liczby rekordów. Gdy to zadziała, przełączymy się na przewijanie.
Teraz możemy dodać przycisk po zakończeniu naszej foreach
pętli, jak poniżej
<x-button wire:click="loadMore">Load More Products</x-button>
Po kliknięciu tego przycisku musimy pobrać kolejne 10 rekordów i dołączyć do bieżącej listy. Jednak Livewire renderuje cały komponent, dzięki czemu możemy użyć podejścia dołączania.
Drugą opcją jest pobranie wszystkich 20 rekordów i ponowne wyrenderowanie komponentu. Da to iluzję ładowania większej ilości danych, ale ma poważne problemy z wydajnością.
Zamiast tego zamierzamy stworzyć kolejny komponent, LoadMoreProducts
. Ten komponent byłby odpowiedzialny za:
- Wyświetlanie powyższego przycisku Załaduj więcej produktów.
- Obsługa zdarzenia kliknięcia, które spowoduje pobranie Produktów na 2. i kolejne strony.
- Warunkowe wyświetlanie widoku związanego z
LoadProducts
Składnik.
Możemy więc utworzyć ten komponent za pomocą poniższego polecenia:
php artisan make:livewire LoadMoreProducts
Dodamy ten komponent w naszym pliku widoku na resources/views/livewire/products/load-products.blade.php
przykład poniżej:
@if($products->hasMorePages())
@livewire('load-more-products', ['page' => $page, 'perPage' => $perPage, 'key' => 'products-page-' . $page])
@endif
Prosimy o zapoznanie się z tym, że wyświetlamy ten Komponent tylko wtedy, gdy do pobrania jest więcej Produktów. Mijamy $page
$perPage
również i Nieruchomość. Używamy również unikalnego klucza, aby go zidentyfikować, ponieważ będzie wiele tych komponentów, 1 dla każdej następnej strony.
W naszym pliku komponentu znajdującym się pod adresem app/Http/Livewire/LoadMoreProducts
, będziemy mieli następujący kod, który na tym etapie jest bardzo podobny do 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');
}
}
W pliku widoku tego komponentu znajdującym się pod adresem resources/views/livewire/products/load-more-products.blade.php
, ostatecznie wyświetlimy nasz przycisk.
<x-button wire:click="loadMore">Load More Products</x-button>
Jak widać, wywołujemy loadMore
metodę za jednym kliknięciem tego przycisku. Musimy zdefiniować tę metodę w LoadMoreProducts
komponencie i będzie ona obsługiwać następujące funkcjonalności:
- Będziemy zwiększać
$page
Właściwość o 1. - Zdefiniujemy nową flagę
loadMore
i ustawimy ją na true. - W ramach metody renderowania sprawdzimy powyższą flagę. Jeśli ta flaga jest prawdziwa, pobierzemy rekordy z bazy danych dla danego
$page
i wyświetlimy widok związany zLoadProducts
komponentem. W przeciwnym razie wyświetlimy tylko widok Związany zLoadMoreProducts
, który renderuje przycisk.
Oto jak wygląda nasz komponent 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
]);
}
}
}
Tak więc, gdy Użytkownik prosi o 2nd Page, pobieramy Produkty związane z 2nd Page i wyświetlamy je za pośrednictwem livewire.products.load-products
. Ten widok wyświetla również przycisk "Załaduj więcej produktów" dla strony 3rd.
W ten sposób, rozbijając funkcjonalność na dwa komponenty, rozwiązaliśmy problem dołączania do aktualnej listy.
Teraz wprowadźmy zmiany, aby załadować więcej produktów podczas przewijania użytkownika, a nie kliknięcia przycisku. Musimy tylko wprowadzić zmiany w widoku LoadMoreProducts
. Musimy uruchomić zdarzenie kliknięcia, gdy użytkownik przewinie do końca listy. Możemy to zrobić, korzystając z x-init
dyrektywy AlpineJs.
<div x-data="{
checkScroll() {
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
@this.call('loadMore')
}
};
}
}"
x-init="checkScroll"
>
Teraz, gdy użytkownik przewinie do końca listy, metoda zostanie uruchomiona, loadMore
a rekordy zostaną dołączone na końcu listy. Otrzymamy takie same dane wyjściowe, jak pokazano na obrazku na początku samouczka.
Jeśli jesteś zainteresowany kodem, możesz go pobrać z Github.
Mam nadzieję, że podobał Ci się ten samouczek. W przypadku podobnych artykułów możesz śledzić mnie na Twitterze