Laravel Livewire to pełnowymiarowy framework Laravel do budowania dynamicznych interfejsów. W nie tak odległej przeszłości, aby zbudować aplikację za pomocą Laravel, musiałeś:
- Write Blade templates and render your app on the server side
- Write your backend as APIs that accept and respond with JSON, and then have a frontend framework like Vue, React, or Angular to consume the APIs and implement the UI
Ale teraz mamy trzecią opcję: Livewire. Chciałbym zagłębić się w zalety i wady opcji 1 i 2 powyżej, ale to już zostało zrobione sprawiedliwie w tym dobrze napisanym poście tutaj.
W tym artykule zagłębimy się w Livewire i zobaczymy, jak można go zastosować w rzeczywistych aplikacjach.
Co zbudujemy Zbudujemy
prostą aplikację blogową z następującymi funkcjami:
- Anyone can create an account and log in
- Logged-in users can create and update their own posts
- Anyone can read posts
Wymagania wstępne i konfiguracja
Ten samouczek zakłada, że masz dość duże doświadczenie z Laravel (zauważ, że ten samouczek używa Laravel 7.x). Nie jest wymagane żadne wcześniejsze doświadczenie z Livewire - myślę, że dlatego tu jesteśmy.
Oczywiście, aby rozpocząć, musimy mieć skonfigurowane nasze środowisko programistyczne. Najpierw utwórz nową aplikację Laravel:composer create-project --prefer-dist laravel/laravel:
^7.0 blog-wire
Następnie zainstaluj pakiet Livewire z composer:
composer require livewire/livewire
Utwórz nową bazę danych i dodaj poświadczenia bazy danych do .env
pliku. I to wszystko, czego potrzebujemy, aby rozpocząć "Livewiring"!
Jak działa Livewire?
Zanim zaczniemy, dobrze jest mieć pojęcie, jak Livewire robi swoje. Krótko mówiąc:
- Livewire renderuje początkowe dane wyjściowe komponentu na stronie — tak, jak typowy szablon Blade renderowany na serwerze
- Gdy dochodzi do interakcji, Livewire wysyła żądanie AJAX do serwera ze zaktualizowanymi danymi
- Serwer ponownie renderuje komponent i odpowiada zaktualizowanym kodem HTML
- Livewire następnie inteligentnie mutuje DOM zgodnie ze zmianą
Jak widać, to tak, jakby mieć frontend i backend w jednym miejscu, bez potrzeby powtarzania logiki.
Kluczowe pojęcia w Livewire Aktywacja Livewire na stronie Aby Livewire działał na stronie, musisz dołączyć style i skrypty Livewire
na każdej stronie
, która ich potrzebuje. Zwykle trafiają one do szablonu podstawowego. Zrobisz to za pomocą @livewireStyles
komponentów @livewireScripts
//app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>@yield('title')</title>
@livewireStyles
</head>
<body>
@yield('content')
@livewireScripts
</body>
</html>
Livewire does all of its goodness around its components. are quite similar to typical Laravel Blade class-based components. Let’s take a quick look at the two.
Tworzenie komponentu
Laravel Blade Komponent Laravel Blade można utworzyć, uruchamiając następujące polecenie:php artisan make:
component Alert
Spowoduje to utworzenie nowego Alert.php
pliku klasy i umieszczenie go w folderzeApp\Views\Components
. Następnie tworzony jest odpowiedni szablon widoku i umieszczany w resources/views/components
programie . Aby wyświetlić składnik, można użyć następującej składni bloku: <x-alert/>
.
Możesz dokładniej zbadać komponenty Laravel Blade w dokumentacji.
Tworzenie komponentu
Livewire Aby utworzyć komponent Livewire, uruchom następujące polecenie:php artisan make:
livewire Alert
Polecenie utworzy również dwa nowe pliki: app\Http\Livewire\Alert.php
i szablon resources/views/livewire/alert.php
widoku .
Komponent Livewire można renderować za pomocą lub <livewire:alert />
@livewire('alert')
.
As you can see, the commands look quite similar. The only major difference is that with , there’s a real-time sync (no page refresh required) between the component class and its view template. We will see how this works shortly.
Właściwości Livewire Właściwości
publiczne klas komponentów są udostępniane w widoku szablonu komponentu. Na tym się nie kończy — wartość właściwości jest synchronizowana w czasie rzeczywistym z widokiem, dzięki czemu po zaktualizowaniu wartości właściwości w widoku jest ona automatycznie aktualizowana w klasie komponentu.
//App\Http\Livewire\Alert.php
<?php
class Alert extends Component{
public $message = "Our alert message";
}
// livewire/alert.blade.php
<div>
<input wire:model="message">
<br/>
{{ $message }}
</div>
Aby powiązać właściwość komponentu z elementem wejściowym HTML, należy użyć następującego sytax:wire:
model="nazwa właściwości"
By typing into the input box, you will see the value of $message
updating in real time. This is very similar to the concept of data binding in frameworks like Vue.js, React, and Angular. Learn more about Właściwości Livewire Właściwości here.
Akcje
Livewire Podobnie jak można powiązać dane w szablonie widoku z publicznymi właściwościami komponentów, można również mapować zdarzenia po stronie klienta na metody w komponentach. Na przykład, można reagować na zdarzenia kliknięcia, keyup i keydown, itp. za pomocą metod zdefiniowanych w klasie komponentu.
Spójrzmy na przykład:
<?php
use Livewire\Component;
class PostAlert extends Component{
public $liked = true;
public function render(){
return view('livewire.post-alert');
}
public function toggleLike(){
$this->liked = !$this->liked;
}
}
// livewire/post-alert.blade.php
<div>
<h4>Seeing livewire action in action 😜</h4>
<button class="btn btn-primary" wire:click="toggleLike()">
Like
</button>
@if ($liked)
<i class="fa fa-heart text-danger h4"></i>
@else
<i class="fa fa-heart text-secondary h4"></i>
@endif
</div>
W powyższej klasie komponentów utworzyliśmy metodętoggleLike()
, która przełącza wartość właściwości na jej przeciwną wartość liked
logiczną. W widoku szablonu mamy przycisk i ikonę serca, która jest w kolorze czerwonym lub szarym w zależności od wartości liked
właściwości.
Użyliśmy składni wire:click=[action name]
do powiązania metody toggleLike
ze zdarzeniem click.
A lot Livewire’s use cases revolve around properties and actions, and as such, they are very important to understand. These concepts can be applied to things like create form
, edit form
, delete form
, etc. Read more about Akcje here.
Walidacja danych Livewire sprawia, że walidacja
danych jest bezproblemowa. Aby sprawdzić poprawność danych pochodzących z widoku szablonu formularza, należy napisać $rules
właściwość zawierającą reguły sprawdzania poprawności, tak jak w przypadku Laravel. Następnie należy wywołać $this→validate()
metodę w trakcie walidacji.
Spójrzmy na formularz do tworzenia wpisu na blogu:
...
class CreatePost extends Component
{
public $title, $body;
public $success;
protected $rules = [
'title' => 'required|string|max:220',
'body' => 'required'
];
public function render()
{
return view('livewire.create-post')
->extends('layouts.app')
->section('content');
}
public function create(){
$this->validate();
Post::create([
'title' => $this->title,
'slug' => Str::slug($this->title),
'body' => $this->body,
'author_id' => auth()->id()
]);
$this->success = true;
}
}
// livewire/create-post
<div class="container">
@if ($success)
<div class="alert alert-success">
Post has been created successfully
</div>
@endif
<form wire:submit.prevent="create">
<div class="form-group">
<label for="Post title">Post title</label>
<input wire:model="title" type="text" name="title" id="title" class="form-control" placeholder="Title of the post">
@error('title') <span class="error">{{ $message }}</span> @enderror
</div>
<div class="form-group">
<label for="Post body">Post Body</label>
<textarea name="body" id="body" placeholder="Body of post here..." wire:model="body" class="form-control"></textarea>
@error('body') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<button class="btn btn-primary" type="submit">Publish</button>
</div>
</form>
</div>
W powyższym kodzie formularza, gdy użytkownik przesyła wpis i nie przechodzi weryfikacji, wyświetlane są błędy sprawdzania poprawności, a wszystko to bez odświeżania strony.
Pierwsze kroki z Laravel Livewire
Dość powiedział - przejdźmy do działania. Możesz śledzić w repozytorium GitHub, gdy tworzymy naszą aplikację demonstracyjną.
Ponieważ chcemy, aby zalogowani użytkownicy mogli zarządzać własnymi postami, muszą najpierw utworzyć konto. Użyjemy do tego wbudowanego systemu uwierzytelniania Laravel.
Najpierw zainstaluj pakiet laravel/ui composer
:composer require laravel/ui
Następnie uruchom php artisan ui vue --auth
rusztowanie całego systemu uwierzytelniania, a następnie php artisan migrate
wykonaj migrację bazy danych.
N.B., most of the things we used to do with controllers will now be done using .
Przejdźmy do tworzenia modelu potrzebnego dla naszej aplikacji postów na blogu, :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
protected $guarded = [];
public function author(){
return $this->belongsTo(User::class, 'author_id', 'id');
}
}
Teraz utworzymy nasz plik migracji, App\Post
php artisan make:migration create_posts_table--table=posts:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug')->unique();
$table->longText('body');
$table->integer('author_id');
$table->timestamps();
$table->softDeletes();
});
Tworzenie komponentów
Będziemy tworzyć komponent dla każdej akcji bloga, którą chcemy, tj. Utwórz post, edytuj post, wyświetlaj listy postów i wyświetlaj post. Idźmy dalej i stwórzmy komponenty:
php artisan make:livewire CreatePost
php artisan make:livewire EditPost
php artisan make:livewire ListPost
php artisan make:livewire HomePost
php artisan make:livewire ReadPost
Możemy renderować komponent Livewire bezpośrednio z tras takich jak: Route::get('/posts/create', [\App\Http\Livewire\CreatePost::
class, '__invoke'])->middleware('auth');
Instead of calling controller actions, we will be routing to the , as shown above. Let’s now add all the routes we’ll need in web.php
:
Route::get('/', function () {
return view('index');
});
Auth::routes();
Route::get('/post/{slug}', [\App\Http\Livewire\ReadPost::class, '__invoke']);
Route::get('/home', '[email protected]')->name('home');
class, '__invoke'])->middleware('auth');
Route::get('/posts/{id}/edit', [\App\Http\Livewire\EditPost::class, '__invoke'])->middleware('auth');
//ListPost.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class ListPost extends Component
{
public function render()
{
$posts = \App\Post::latest()->paginate(20);
return view('livewire.list-post', ['posts' => $posts])
->extends('layouts.app')
->section('content');
}
}
//livewire/list-post.blade.php
<div>
<h4>My Posts <a href="{{ url('posts/create') }}" class="btn btn-primary"><i class="fa fa-plus"></i> Add new</a></h4>
<ul class="list-group list-group-flush">
@forelse ($posts as $post)
<li class="list-group-item">
<div class="float-right">
<a href='{{ url("posts/{$post->id}/edit") }}' class="btn btn-primary"><i class="fa fa-edit"></i> Edit</a>
</div>
<div>
<h5>{{ $post->title }}</h5>
<p>{!! substr(strip_tags($post->body), 0, 200) !!}</p>
<small class="text-muted">Published {{ $post->created_at }}</small>
</div>
</li>
@empty
<li>You have not written any posts yet, write one now</li>
@endforelse
</ul>
</div>
//CreatePost.php
<?php
namespace App\Http\Livewire;
use App\Post;
use Livewire\Component;
use Illuminate\Support\Str;
class CreatePost extends Component
{
public $title, $body;
public $success;
protected $rules = [
'title' => 'required|string|max:220',
'body' => 'required'
];
public function render()
{
return view('livewire.create-post')
->extends('layouts.app')
->section('content');
}
public function create(){
$this->validate();
Post::create([
'title' => $this->title,
'slug' => Str::slug($this->title),
'body' => $this->body,
'author_id' => auth()->id()
]);
$this->success = true;
}
}
W powyższym komponencie tworzymy zmienne publiczne do przechowywania tytułu i treści posta na blogu, a także zmienną wskazującąsuccess
, czy tworzenie posta się powiedzie.
W metodzie render()
Livewire pozwala nam określić plik układu do wykorzystania do renderowania komponentu i sekcję, w której chcemy go wyświetlić odpowiednio za pomocą extends()
metod isection()
.
Teraz widok szablonu wygląda następująco:Jeśli przejdziesz do przeglądarki do /posts/create
, powinieneś zobaczyć wyświetlony formularz tworzenia:
<div class="container">
@if ($success)
<div>
<div class="alert alert-success">
Post has been created successfully. <a href="{{ url('/home') }}">View all posts</a>
</div>
</div>
@endif
<form wire:submit.prevent="create">
<div class="form-group">
<label for="Post title">Post title</label>
<input wire:model="title" type="text" name="title" id="title" class="form-control" placeholder="Title of the post">
@error('title') <span class="error">{{ $message }}</span> @enderror
</div>
<div class="form-group">
<label for="Post body">Post Body</label>
<textarea name="body" id="body" placeholder="Body of post here..." wire:model="body" class="form-control"></textarea>
@error('body') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<button class="btn btn-primary" type="submit">Publish</button>
</div>
</form>
</div>
Jest to dość podstawowy przykład tego,
jak Livewire może być stosowany w prawdziwym świecie.
Wniosek:
Livewire wypełnia lukę między backendem a frontendem. Korzystasz z interaktywności w czasie rzeczywistym bez konieczności samodzielnego pisania dużej ilości kodu JavaScript. Jeśli korzystałeś wcześniej z Vue.js, bardzo łatwo jest dostrzec zalety Livewire.
Livewire nie jest dobrym wyborem dla aplikacji, które są bardzo wymagające po stronie klienta. Ale w sytuacjach, w których potrzebujesz aplikacji renderowanej na serwerze z odrobiną reaktywności, Livewire będzie Ci dobrze służyć.
Ponownie, aplikację, którą zbudowaliśmy w tym samouczku, można znaleźć naGonoHUb.