Byłem fanem Laravel Livewire od czasu jego pierwszego wydania i używałem go wiele razy do tworzenia wspaniałych interfejsów użytkownika dla aplikacji. Jedną z rzeczy, które często robię, jest tworzenie wyodrębnionych komponentów, do których mogę przekazać innym - na przykład, aby nie mieć 20 różnych modów lub suwaków.
W tym samouczku omówię, w jaki sposób można utworzyć komponent typu slide-over dla aplikacji TALL Stack, abyś Ty również mógł wdrożyć to podejście.
Zakładam, że Ty zainstalowałeś już Laravel i Livewire i masz skonfigurowaną podstawową aplikację. Do stylizacji użyję Tailwind UI i Tailwind CSS, ponieważ nie mam pojęcia, jak cokolwiek zaprojektować.
Zacznijmy od stworzenia ogólnego komponentu w Livewire o nazwie SidePanel
, który będzie zawierał cały kod i elementy sterujące wymagane do otwierania i zamykania panelu. Zacznijmy budować.
php artisan livewire:make SidePanel --test
Najpierw musimy mieć dostępny stan, aby mógł być otwarty lub zamknięty, co, na pewno się zgodzisz, jest istotnym aspektem panelu bocznego.
<declare(strict_types=1);
namespace App\Http\Livewire;
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
final class SidePanel extends Component
{
public bool $open = false;
public function render(): ViewContract
{
return View::make(
view: 'livewire.side-panel',
);
}
}
Tutaj mamy standardowy komponent Livewire, dostosowany na mój bardzo uparty sposób. Do tej pory mamy jedną właściwość o nazwie open
- którą „splączemy” na interfejsie użytkownika za pomocą AlpineJS. Potrzebujemy kilku innych właściwości, abyśmy mogli wyświetlić panel i nie zawiesić się, jeśli komponent nie zostanie przekazany.
declare(strict_types=1);
namespace App\Http\Livewire;
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
final class SidePanel extends Component
{
public bool $open = false;
public string $title = 'Default Panel';
public string $component = '';
public function render(): ViewContract
{
return View::make(
view: 'livewire.side-panel',
);
}
}
Mamy domyślny tytuł i właściwość komponent
, która pozwala nam wybrać, który komponent jest ładowany. W ten sposób inne komponenty, które z nim rozmawiają, mogą mu powiedzieć, co załadować i przekazać tytuł, który ma zostać wyświetlony. Przyjrzyjmy się szablonowi tego komponentu:
<section
x-data="{ open: @entangle('open') }"
@keydown.window.escape="open = false"
x-show="open"
x-cloak
class="relative z-10"
aria-labelledby="slide-over-title"
x-ref="dialog"
aria-modal="true"
>
<div
x-show="open"
x-cloak
x-transition:enter="ease-in-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
></div>
<div class="fixed inset-0 overflow-hidden">
<div class="absolute inset-0 overflow-hidden">
<div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
<div
x-show="open"
x-cloak
x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
x-transition:enter-start="translate-x-full"
x-transition:enter-end="translate-x-0"
x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="translate-x-full"
class="pointer-events-auto w-screen max-w-md"
@click.away="open = false"
>
<div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
<header class="px-4 sm:px-6">
<div class="flex items-start justify-between">
<h2 class="text-lg font-medium text-gray-900" id="slide-over-title">
Panel title
</h2>
<div class="ml-3 flex h-7 items-center">
<button
type="button"
class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
@click="open = false"
>
<span class="sr-only">Close panel</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
</header>
<article class="relative mt-6 flex-1 px-4 sm:px-6">
@if ($component)
@livewire($component)
@else
<div class="absolute inset-0 px-4 sm:px-6">
<div class="h-full border-2 border-dashed border-gray-200" aria-hidden="true"></div>
</div>
@endif
</article>
</div>
</div>
</div>
</div>
</div>
</section>
Tutaj mamy sporo znaczników do kontrolowania, jak wygląda i zachowuje się, używając @entangle
do komunikacji między AlpineJS i Livewire. Sprawdzamy, czy komponent
został ustawiony, a jeśli nie, wyświetlamy pusty stan. Następnie musimy wyzwolić to z innych komponentów - wysyłając mu trochę danych, abyśmy mogli wybrać komponent do załadowania i tytuł do ustawienia. To zadziała zarówno z Livewire, jak i Alpine, ale w moim przykładzie użyję innego komponentu Livewire, aby wywołać otwarcie panelu.
$this->emit('openPanel', 'New Title', 'component.name.with-namespace');
Przekazujemy trzy parametry metodą emit
. Po pierwsze, nazwa wydarzenia, które odpalamy. Po drugie, tytuł panelu. Na koniec chcemy przekazać sam komponent tak, jakbyśmy ładowali go za pomocą dyrektywy livewire w twoim widoku.
Teraz musimy poprosić nasz komponent Panelu bocznego, aby nasłuchiwał tego zdarzenia i miał metoda, która obsłuży logikę aktualizacji jej właściwości.
declare(strict_types=1);
namespace App\Http\Livewire;
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
final class SidePanel extends Component
{
public bool $open = false;
public string $title = 'Default Panel';
public string $component = '';
protected $listeners = [
'openPanel'
];
public function openPanel(string $title, string $component): void
{
$this->open = true;
$this->title = $title;
$this->component = $component;
}
public function render(): ViewContract
{
return View::make(
view: 'livewire.side-panel',
);
}
}
Gdy słuchacz zaakceptuje wszystkie wymagane parametry i Alpine obsługuje stan otwarty i zamknięty - możemy zamknąć ten panel i wymienić pokazany komponent.
To podejście pozwoliło mi na stworzenie czystego użytkownika interfejsy, które otwierają oddzielny komponent w razie potrzeby. Ponadto komponent, przez który przechodzimy do panelu, może nadal być używany jako izolowany komponent dla widoku.
Jak radzisz sobie z tymi przypadkami użycia w swoich projektach? Jak myślisz, jak to się zmieni w Livewire v3? Podziel się z nami swoimi przemyśleniami na Twitterze.