• Время чтения ~7 мин
  • 13.07.2022

Laravel Livewire — это полнофункциональный фреймворк Laravel для создания динамических интерфейсов. В недалеком прошлом, чтобы создать приложение с помощью Laravel, вам нужно было:

  1. Write Blade templates and render your app on the server side
  2. 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

Но теперь у нас есть третий вариант: Livewire. Я бы с удовольствием подробно остановился на плюсах и минусах вариантов 1 и 2 выше, но это уже было сделано справедливо в этом хорошо написанном посте здесь.

В этой статье мы углубимся в Livewire и посмотрим, как его можно применить в реальных приложениях.

Что мы будем строить

Мы создадим простое приложение для ведения блога со следующими функциями:

  1. Anyone can create an account and log in
  2. Logged-in users can create and update their own posts
  3. Anyone can read posts

Предварительные требования и настройка

В этом руководстве предполагается, что вы достаточно опытны в работе с Laravel (обратите внимание, что в этом руководстве используется Laravel 7.x). Никакого предварительного опыта работы с Livewire не требуется — я думаю, что именно поэтому мы все равно здесь.

Конечно, для начала мы должны настроить нашу среду разработки. Во-первых, создайте новое приложение Laravel:composer create-project --prefer-dist laravel/laravel:

^7.0 blog-wire

Затем установите пакет Livewire с помощью composer:

composer require livewire/livewire

Создайте новую базу данных и добавьте в нее учетные данные .env базы данных. И это все, что нам нужно для начала работы с "Livewiring"!

Как работает Livewire?

Прежде чем мы начнем, полезно иметь представление о том, как Livewire делает свое дело. Резюмируя:

  • Livewire визуализирует начальный вывод компонента на страницу — да, как типичный шаблон Blade, визуализированный сервером
  • Когда происходит взаимодействие, Livewire делает AJAX-запрос к серверу с обновленными данными
  • Сервер повторно визуализирует компонент и отвечает обновленным HTML-кодом
  • Затем Livewire интеллектуально изменяет DOM в соответствии с тем, что изменилось

Как видите, это похоже на то, что ваш фронтенд и бэкенд находятся в одном месте, без необходимости повторять логику.

Основные понятия в Livewire Активация Livewire на странице Чтобы Livewire работал на странице

, необходимо включить стили и сценарии Livewire

на каждую страницу, которая в них нуждается. Обычно они входят в ваш базовый шаблон. Вы бы сделали это, используя @livewireStyles и @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 компоненты

Livewire does all of its goodness around its components. Livewire компоненты are quite similar to typical Laravel Blade class-based components. Let’s take a quick look at the two.

Создание компонента

Laravel Blade Компонент Laravel Blade можно создать, выполнив следующую команду:php artisan make:

component Alert

Это создаст новый Alert.php файл класса и поместит его в App\Views\Components папку. Затем создается соответствующий шаблон представления, который помещается в resources/views/components. Чтобы отобразить компонент, можно использовать следующий синтаксис колонки: <x-alert/>.

Вы можете более подробно изучить компоненты Laravel Blade в документации.

Создание компонента

Livewire Чтобы создать компонент Livewire, выполните следующую команду:php artisan make:

livewire Alert

Команда также создаст два новых файла: app\Http\Livewire\Alert.php и шаблон resources/views/livewire/alert.phpпредставления .

Компонент Livewire можно визуализировать с помощью любого <livewire:alert /> или @livewire('alert').

As you can see, the commands look quite similar. The only major difference is that with Livewire компоненты, 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.

Свойства

Livewire Общедоступные свойства классов компонентов становятся доступными в представлении шаблона компонента. И это еще не все — значение свойства синхронизируется в режиме реального времени с представлением, так что при обновлении значения свойства в представлении оно автоматически обновляется в классе компонентов.

//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>

Чтобы привязать свойство компонента к входному элементу html, вы должны использовать следующий sytax:wire:

model="property name"

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 Свойства here.

Действия

Livewire Точно так же, как можно привязать данные в шаблоне представления к открытым свойствам компонентов, можно также сопоставить события на стороне клиента с методами в компонентах. Например, вы можете реагировать на события щелчка, нажатия клавиши и т. д., используя методы, определенные в классе компонентов.

Давайте посмотрим на пример:

<?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>

В приведенном выше классе компонента мы создали методtoggleLike(), который переключает значение свойства на противоположное логическое значениеliked. В представлении шаблона у нас есть кнопка и значок сердца, которые окрашены в красный или серый цвет в зависимости от значения liked свойства.

Мы использовали синтаксис wire:click=[action name] для привязки toggleLike метода к событию click.

Livewire Action ToggleLike Event
Livewire action toggling a button.

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 Действия here.

Проверка

данных Livewire делает проверку данных бесшовной. Для проверки данных, поступающих из представления шаблона формы, необходимо написать $rules свойство, содержащее правила проверки, как и в Laravel. После этого вы вызываете $this→validate() метод in, выполняющий проверку.

Давайте посмотрим на форму для создания записи в блоге:

 ...
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>
 
В приведенном выше коде формы, когда пользователь отправляет сообщение, и оно не проходит проверку, отображаются ошибки проверки, и все это без обновления страницы.

Приступая к работе с Laravel Livewire

Достаточно сказано — давайте перейдем к действиям. Вы можете следить в репозитории GitHub за созданием демонстрационного приложения.

Поскольку мы хотим, чтобы вошедшие в систему пользователи могли управлять своими собственными сообщениями, они должны сначала создать учетную запись. Для этого мы будем использовать встроенную систему аутентификации Laravel.

Во-первых, установите пакет laravel/ui composer:

composer require laravel/ui

Затем запустите php artisan ui vue --auth всю систему аутентификации, а затем php artisan migrate выполните миграцию БД.

N.B., most of the things we used to do with controllers will now be done using Livewire компоненты.

Давайте перейдем к созданию модели, необходимой для нашего приложения для сообщений в блоге: Теперь мы создадим наш файл миграции, App\Post

<?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');
    }
}


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();
});

Создание компонентов

Мы будем создавать компонент для каждого действия блога, которое мы хотим, т. е. создавать сообщения, редактировать сообщения, перечислять сообщения и просматривать сообщения. Давайте продолжим и создадим компоненты:

  • 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

Мы можем визуализировать компонент Livewire непосредственно из таких маршрутов:Route::get('/posts/create', [\App\Http\Livewire\CreatePost::

class, '__invoke'])->middleware('auth');

Instead of calling controller actions, we will be routing to the Livewire компоненты, 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;
    }
}

В приведенном выше компоненте мы создаем общедоступные переменные для хранения заголовка и основного содержимого сообщения в web.phpблоге, а также переменнуюsuccess, указывающую, успешно ли создано сообщение.

В этом методе Livewire позволяет нам указать файл макета, который будет использоваться при рендеринге render() компонента, и раздел, в котором мы хотим, чтобы он отображался с помощью extends() методов и section() соответственно.

Теперь представление шаблона выглядит следующим образом:Если вы перейдете в браузере на /posts/create, вы должны увидеть отображаемую форму создания:

<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"&gt;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>

Creation Form Display

Это довольно простой пример того, как Livewire может быть применен в реальном мире.

Заключение

Livewire устраняет разрыв между бэкендом и фронтендом. Вы получаете преимущество интерактивности в реальном времени без необходимости писать много JavaScript самостоятельно. Если вы использовали Vue.js раньше, очень легко увидеть преимущества Livewire.

Livewire — не лучший выбор для приложений, которые сильно требовательны к клиентской стороне. Но в ситуациях, когда вам нужно приложение, отображаемое на сервере, с небольшим количеством реактивности, Livewire сослужит вам хорошую службу.

Опять же, приложение, которое мы создали в этом уроке, можно найти наGоноHУБ.

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