51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

前端开发库:教你Laravel Livewire入门

500.jpg

作为开发人员,我们一直在寻找使我们的生活更轻松的工具,库和框架。对于Laravel开发人员而言,这没什么不同。这就是为什么我们喜欢这个框架的原因,因为一切对我们来说都很容易-使我们能够专注于构建出色的应用程序,而不会为如何实现实现而烦恼。

在本教程中,我们将研究另一个工具,该工具可以使您成为Laravel开发人员更加轻松。具体来说,我们将研究Livewire,这是Laravel的全栈框架,可让我们无需编写大量JavaScript即可构建动态接口。基本上所有事情都是由您作为Laravel开发人员已经熟悉的工具完成的。

什么是Livewire?

Livewire[https://laravel-livewire.com/]是一个库,它使我们能够使用Blade和一些JavaScript来构建反应和动态接口。我说"一点",是因为我们只打算编写JavaScript来通过浏览器事件传递数据并对其进行响应。

您可以使用Livewire来实现以下功能,而无需重新加载页面:

  • 分页

  • 表格验证

  • 通知

  • 文件上传预览

请注意,Livewire不仅限于上述功能。您可以使用更多功能。上面的功能只是您可能想在应用程序中实现的最常见功能。

Livewire与Vue

Vue一直是Laravel开发人员向其应用程序添加交互性的首选前端框架。如果您已经在使用Vue为应用程序供电,则Livewire是可选的供您学习。但是,如果您不熟悉使用Laravel进行前端,并且打算将Livewire替换为Vue,那么可以,可以使用Livewire替代Vue。学习曲线
不会像学习Vue那样陡峭,因为您将主要使用Blade来编写模板文件。

有关Livewire和Vue进行比较的更多信息,请查看" Laravel Livewire vs Vue[https://blog.logrocket.com/livewire-vs-vue/] "。

应用概述

我们将创建一个实时CRUD应用程序。因此,它基本上是没有页面重新加载的CRUD应用。Livewire将处理更新UI所需的所有AJAX请求。这包括通过搜索字段过滤结果,通过列标题排序以及简单的分页(上一个和下一个)。创建和编辑用户将使用Bootstrap模式。

11.jpg

您可以在其GitHub repo【https://github.com/sitepoint-editors/livecrud】上查看该项目的源代码。

先决条件

本教程假定您具有PHP应用程序开发经验。Laravel的经验会有所帮助,但不是必需的。如果您只知道纯PHP或其他PHP框架,仍然可以继续学习。

本教程假定您在计算机上安装了以下软件:

  • PHP

  • MySQL

  • NGINX

  • Composer

  • Node and npm

如果您使用的是Mac,则比安装MySQL和NGINX更为方便的选择是安装DBngin和Laravel Valet。

设置项目

您现在可以创建一个新的Laravel项目:

composer create-project laravel/laravel livecrud

浏览livecrud将要生成的文件夹。这将是根项目文件夹,您可以在其中执行本教程中的所有命令。

下一步是使用您选择的数据库管理工具创建MySQL数据库。将数据库命名为livecrud

安装后端依赖项

后端只有一个依赖关系,那就是Livewire。使用以下命令安装它:

composer require livewire/livewire:2.3

注意:我们正在安装创建演示时使用的特定版本。如果将来要阅读此书,建议您安装最新版本。不要忘记在其GitHub存储库上检查项目的变更日志,以确保您没有丢失任何内容。

设置数据库

更新用于创建users表的默认迁移,并添加我们将要使用的自定义字段:

// database/migrations/<timestamp>_create_users_table.phppublic function up(){
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->enum('user_type', ['admin', 'user'])->default('user'); // add this
        $table->tinyInteger('age'); // add this
        $table->string('address')->nullable(); // add this
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });}

接下来,更新database/factories/UserFactory.php文件并为我们添加的自定义字段提供值:

// database/factories/UserFactory.phppublic function definition(){
    return [
        'name' => $this->faker->name,
        'email' => $this->faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
        // add these
        'user_type' => 'user',
        'age' => $this->faker->numberBetween(18, 60),
        'address' => $this->faker->address,
    ];}

最后,打开database/seeders/DatabaseSeeder.php文件并取消对该调用的注释以创建虚拟用户:

// database/seeders/DatabaseSeeder.phppublic function run(){
    \App\Models\User::factory(100)->create();}

不要忘记.env使用将要使用的测试数据库来更新文件。在这种情况下,我将数据库命名为livecrud。完成后,运行迁移和种子器以填充数据库:

php artisan migratephp artisan db:seed

设置前端依赖项 {#settingupfrontenddependencies}

为简化起见,我们将使用Laravel支架进行Bootstrap。要使用它,您首先需要安装laravel/ui软件包:

composer require laravel/ui

接下来,安装Bootstrap4。这将在您的webpack.mix.js文件上添加配置并创建resources/js/app.jsresources/sass/app.scss文件:

php artisan ui bootstrap

接下来,将Font Awsome添加到resources/sass/app.scss文件中。默认情况下,其中应该已经有字体,变量和引导程序导入:

// Fonts@import url("https://fonts.googleapis.com/css?family=Nunito");// Variables@import "variables";// Bootstrap@import "~bootstrap/scss/bootstrap";// add these:@import "~@fortawesome/fontawesome-free/scss/fontawesome";@import "~@fortawesome/fontawesome-free/scss/brands";@import "~@fortawesome/fontawesome-free/scss/regular";@import "~@fortawesome/fontawesome-free/scss/solid";

完成后,安装所有依赖项:

npm install @fortawesome/fontawesome-freenpm install

创建Livewire组件

您可以使用以下make:livewire命令来创建新的Livewire组件:

php artisan make:livewire LiveTable

这将创建以下文件:

  • app/Http/Livewire/LiveTable.php ---组件的控制器

  • resources/views/livewire/live-table.blade.php ---组件的视图文件

打开resources/views/livewire/live-table.blade.php文件并添加以下内容:

<div>
    <div class="row mb-4">
        <div class="col-md-12">
          <div class="float-right mt-5">
              <input wire:model="search" class="form-control" type="text" placeholder="Search Users...">
          </div>
        </div>
    </div>
    <div class="row">
        @if ($users->count())
        <table class="table">
            <thead>
                <tr>
                    <th>
                        <a wire:click.prevent="sortBy('name')" role="button" href="#">
                            Name
                            @include('includes.sort-icon', ['field' => 'name'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('email')" role="button" href="#">
                            Email
                            @include('includes.sort-icon', ['field' => 'email'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('address')" role="button" href="#">
                            Address
                            @include('includes.sort-icon', ['field' => 'address'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('age')" role="button" href="#">
                            Age
                            @include('includes.sort-icon', ['field' => 'age'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('created_at')" role="button" href="#">
                        Created at
                        @include('includes.sort-icon', ['field' => 'created_at'])
                        </a>
                    </th>
                    <th>
                        Delete
                    </th>
                    <th>
                        Edit
                    </th>
                </tr>
            </thead>
            <tbody>
                @foreach ($users as $user)
                    <tr>
                        <td>{{ $user->name }}</td>
                        <td>{{ $user->email }}</td>
                        <td>{{ $user->address }}</td>
                        <td>{{ $user->age }}</td>
                        <td>{{ $user->created_at->format('m-d-Y') }}</td>
                        <td>
                            <button class="btn btn-sm btn-danger">
                            Delete
                            </button>
                        </td>
                        <td>
                            <button class="btn btn-sm btn-dark">
                            Edit
                            </button>
                        </td>
                    </tr>
                @endforeach
            </tbody>
        </table>
        @else
            <div class="alert alert-warning">
                Your query returned zero results.
            </div>
        @endif
    </div>
    <div class="row">
        <div class="col">
            {{ $users->links() }}
        </div>
    </div></div>

这是很多代码,所以让我们从头到尾进行分解。首先,我们有用于搜索用户的搜索字段。我们希望用户在键入时能够看到其查询结果。我们实现的方法是使用wire:model。这使我们可以从组件类(LiveTable)中传入变量的名称。然后,无论用户在此字段中键入什么内容,都将同步到该变量的值。在这种情况下,我们将绑定search变量:

<input wire:model="search" class="form-control" type="text" placeholder="Search Users...">

稍后在LiveTable组件类的代码中,您将看到绑定变量,如下面的代码所示。这些在Livewire中称为属性。如果您来自Vue,则相当于该州。只能public直接从前端访问属性:

// app/Http/Livewire/LiveTable.php<?phpclass LiveTable extends Component{
  public $search = ''; // don't add this yet}

接下来,我们有了表头。在这里,我们wire:click.prevent用来侦听link元素中的click事件。这些在Livewire中称为动作。实际上,它们使您可以侦听浏览器事件,但可以使用后端中的方法对其进行响应。使用.prevent阻止默认浏览器操作。您为此提供的值是您要在组件类中执行的方法的名称。在这种情况下为sortBy。然后,我们传递要排序的列的名称:

<th>
  <a wire:click.prevent="sortBy('name')" role="button" href="#">
      Name
      @include('includes.sort-icon', ['field' => 'name'])
  </a></th>

这是组件类中相应方法的外观。我们稍后将添加代码:

// app/Http/Livewire/LiveTable.phppublic function sortBy($field){
  //}

在以上代码中,我们包含了另一个名为的视图文件sort-icon。创建一个resources/views/includes/sort-icon.blade.php文件并添加以下内容。这将根据用户选择的当前排序呈现当前排序图标:

@if ($sortField !== $field)
    <i class="text-muted fas fa-sort"></i>@elseif ($sortAsc)
    <i class="fas fa-sort-up"></i>@else
    <i class="fas fa-sort-down"></i>@endif

标记就差不多了。其余代码基本上与标准Blade模板相同。因此,我们仍然使用该links()方法显示分页,并使用@if指令有条件地显示某些内容。

现在,我们进入组件类。打开app/Http/Livewire/LiveTable.php文件并对其进行更新,使其包含以下代码:

<?phpnamespace App\Http\Livewire;use Livewire\Component;use Livewire\WithPagination;use App\Models\User;class LiveTable extends Component{
    use WithPagination;

    public $sortField = 'name'; // default sorting field
    public $sortAsc = true; // default sort direction
    public $search = '';

    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortAsc = !$this->sortAsc;
        } else {
            $this->sortAsc = true;
        }

        $this->sortField = $field;
    }

    public function render()
    {
        return view('livewire.live-table', [
            'users' => User::search($this->search)
                ->orderBy($this->sortField, $this->sortAsc ? 'asc' : 'desc')
                ->simplePaginate(10),
        ]);
    }}

如前所述,我们已通过将该search变量的值绑定到客户端中的特定文本字段wire:model。因此,每次用户键入内容时,search变量也会更新。并且在更新时,该组件也会重新呈现。这是因为在render()函数中,我们依赖于search变量的值来获取用户数据。因此,对于每次击键,我们实际上都是通过提供用户的查询和选定的排序来从数据库中获取数据(我们稍后将在"优化"部分中研究如何改进此操作):

User::search($this->search)
                ->orderBy($this->sortField, $this->sortAsc ? 'asc' : 'desc')
                ->simplePaginate(10)

sortBy()方法是我们用来更新用于对users表进行排序的字段的方法。每个字段可以按升序或降序排序。默认情况下,单击排序字段将按升序对其进行排序。再次单击将执行相反的操作:

public function sortBy($field){
    if ($this->sortField === $field) {
        $this->sortAsc = !$this->sortAsc; // if field is already sorted, use the opposite instead
    } else {
        $this->sortAsc = true; // sort selected field by ascending by default
    }
    $this->sortField = $field;}

在过滤users表时,我们使用该search()方法。但是我们还没有添加。更新app/Models/User.php文件以包括该search()方法。这会将用户表过滤为仅返回类型为的用户user。然后,其余条件将是我们要用于过滤搜索字段的字段:

protected $casts = [
    //];public static function search($query){
    return empty($query) ? static::query()->where('user_type', 'user')
        : static::where('user_type', 'user')
            ->where(function($q) use ($query) {
                $q
                    ->where('name', 'LIKE', '%'. $query . '%')
                    ->orWhere('email', 'LIKE', '%' . $query . '%')
                    ->orWhere('address', 'LIKE ', '%' . $query . '%');
            });}

使用Livewire组件

一旦完成,搜索和排序功能就可以使用了。打开routes/web.php文件,并用以下内容替换现有路由:

Route::get('/', function () {
    return view('index');});

接下来,创建一个resources/views/index.blade.php文件并添加以下内容。这是我们使用创建的Live Table组件的地方。我们可以像使用标准组件一样将其呈现到页面中。唯一的区别是,我们需要为组件名称加上前缀,livewire:并且还需要使用它@livewireScripts来呈现Livewire JavaScript文件:

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name') }}</title>
    <link rel="stylesheet" type="text/css" href="{{ asset('css/app.css') }}"></head><body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-9">
                <livewire:live-table />
            </div>
        </div>
    </div>
    @livewireScripts
    <script src="{{ asset('js/app.js') }}"></script></body></html>

此时,您现在可以开始运行该应用程序了。最简单的方法是使用Artisan服务该项目:

php artisan serve

然后在浏览器中通过http://127.0.0.1:8000/访问该应用。

如果您通过Laravel Valet或其他工具设置了本地域,则也可以使用它。

删除用户

接下来,让我们实现用户的删除。就像之前一样,我们使用wire:click侦听"删除"按钮上的点击事件。仅这次,我们不会直接在组件类中调用方法。那是因为这是一个删除操作。我们不希望用户误删除某人,因此我们需要显示某种确认信息才能继续删除。这是Livewire Events的完美用例。这使我们能够与服务器之间发送和接收特定事件。您可以通过调用$emit()方法来使用它。它的第一个参数将是事件的名称,而后面的参数是您要传递给该事件的侦听器的参数。在这种情况下,我们有deleteTriggered 事件,我们将用户的ID和名称作为参数传递给侦听器。

打开resources/views/livewire/live-table.blade.php文件并更新删除按钮的代码:

<button class="btn btn-sm btn-danger" wire:click="$emit('deleteTriggered', {{ $user->id }}, '{{ $user->name }}')">
  Delete</button>

然后,我们可以在服务器或客户端上监听该事件。由于我们只想在触发此事件时显示确认,因此我们在客户端侦听它。创建一个resources/js/users.js文件并添加以下内容。如您所见,我们通过传递给侦听器的参数来访问用户的idname

Livewire.on("deleteTriggered", (id, name) => {
    const proceed = confirm(`Are you sure you want to delete ${name}`);
    if (proceed) {
        Livewire.emit("delete", id);
    }});

用户同意后,我们将发出事件,该事件实际上将删除用户。要在后端侦听事件,请创建一个$listeners数组,其中包含侦听器的名称以及它们映射到的类方法。在这种情况下,事件的名称与方法相同,因此我们只需添加即可。delete.delete()方法随后将删除具有以下内容的用户id

// app/Http/Livewire/LiveTable.phpprotected $listeners = ['delete'];public function sortBy($field){
    //}public function delete($id){
    User::find($id)
        ->delete();}

如果要在删除用户时发出某种通知,则可以调度浏览器事件:

User::find($id)
        ->delete();$this->dispatchBrowserEvent('user-deleted', ['user_name' => $user->name]); // add this

然后在客户端,通过标准浏览器事件监听器API监听此事件。在这里,我们仅显示一个警报,其中包含已删除用户的名称:

// resources/js/users.jswindow.addEventListener("user-deleted", (event) => {
    alert(`${event.detail.user_name} was deleted!`);});

最后,不要忘记将users.js文件添加到webpack.mix.js

// webpack.mix.jsmix.js("resources/js/app.js", "public/js")
    .sass("resources/sass/app.scss", "public/css")
    .js("resources/js/users.js", "public/js") // add this
    .sourceMaps();

此时,如果您在浏览器上尝试删除用户,现在应该可以使用。

创建新用户

让我们继续创建新用户。打开resources/views/livewire/live-table.blade.php文件并添加用于创建新用户的按钮。再次,我们wire:click用来触发一个称为的事件triggerCreate

<div>
    <div class="row mb-4">
        <div class="col-md-12">
            <div class="float-left mt-5">
                <button class="btn btn-success" wire:click="$emit('triggerCreate')">Create New User</button>
            </div>
            <div class="float-right mt-5">
                <input wire:model="search" class="form-control" type="text" placeholder="Search Users...">
            </div>
        </div>
    </div>
    <!-- code for the users table from earlier -->
    <div class="row">
        @if ($users->count())
        @endif
    </div>
</div>

然后在您的resources/js/users.js文件中,侦听此事件并打开模式:

Livewire.on("triggerCreate", () => {
    $("#user-modal").modal("show");
});

注意:上面的代码并不是真正的" Livewire Purist"处理方式。通常,如果您使用Livewire,则希望所有交互都由Livewire处理,其中包括模态。在这种情况下,我们使用jQuery打开模式。这是可以原谅的,因为它只是一行代码。但是,如果您想使用Livewire,则正确的处理方式是对所有内容都使用Livewire。您无法将其与jQuery混合使用。当您以后需要添加前端测试时,这将使事情变得容易。

我们实际上还没有创建Livewire组件,所以让我们继续进行操作:

php artisan make:livewire UserForm

就像Live Table一样,这会创建组件类以及视图文件:

  • app/Http/Livewire/UserForm.php

  • resources/views/livewire/user-form.blade.php

首先,打开视图文件并添加以下内容。该代码看起来很熟悉,因为其中大多数只是用于呈现表单的标准Blade模板。唯一的区别是我们为它添加了一些Livewire属性,您已经熟悉了所有这些属性:

<!-- resources/views/livewire/user-form.blade.php --><div>
    <form wire:submit.prevent="save">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" id="name" name="name" wire:model="name">
            @error('name') <span class="text-danger">{{ $message }}</span> @enderror        </div>
        <div class="form-group">
            <label for="exampleInputPassword1">Email</label>
            <input type="email" class="form-control" id="email" name="email" wire:model="email">
            @error('email') <span class="text-danger">{{ $message }}</span> @enderror        </div>
        <div class="form-group">
            <label for="age">Age</label>
            <input type="number" class="form-control" id="age" name="age" wire:model="age">
            @error('age') <span class="text-danger">{{ $message }}</span> @enderror        </div>
        <div class="form-group">
            <label for="address">Address</label>
            <input type="text" class="form-control" id="address" name="address" wire:model="address">
            @error('address') <span class="text-danger">{{ $message }}</span> @enderror        </div>
        <button class="btn btn-primary" type="submit">Save</button>
    </form></div>

至此,您已经知道wire:submit.prevent="save"单击保存按钮时将触发该事件。.prevent阻止默认操作,即默认提交表单。然后,我们wire:model将每个字段绑定到组件类中的特定属性。

此代码的另一件事:这是用于显示表单错误的标准Blade模板代码。您可能想知道当我们使用Livewire组件时,它在做什么。好吧,答案是Livewire也可以利用此代码向我们展示表单错误。因此,如果用户提交表单时未向特定字段提供值,则服务器将发出警告,并会触发以下错误以显示:

@error('name') <span class="text-danger">{{ $message }}</span> @enderror

接下来,打开resources/views/index.blade.php文件并添加模态的标记:

<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-9">
            <livewire:live-table />
        </div>
    </div></div><!-- add this --><div class="modal" tabindex="-1" role="dialog" id="user-modal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">User</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <livewire:user-form>
            </div>
        </div>
    </div></div>

现在我们有了前端的代码,下面让我们看一下后端。打开app/Http/Livewire/UserForm.php并添加以下内容:

<?phpnamespace App\Http\Livewire;use Livewire\Component;use App\Models\User; // add thisclass UserForm extends Component{

    // add these
    public $name;
    public $email;
    public $age;
    public $address;

    public function render()
    {
        return view('livewire.user-form');
    }

    // add this
    public function save()
    {
        $validated = $this->validate([
            'name' => 'required|min:10',
            'email' => 'required|email|min:10',
            'age' => 'required|integer',
            'address' => 'required|min:10',
        ]);

        User::create(array_merge($validated, [
            'user_type' => 'user',
            'password' => bcrypt($this->email)
        ]));

        $this->resetForm();
        $this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);
        $this->emitTo('live-table', 'triggerRefresh');
    }

    public function resetForm()
    {
        $this->user_id = null;
        $this->name = null;
        $this->email = null;
        $this->age = null;
        $this->address = null;
    }}

数量很多,但是大多数内容对您来说已经很有意义,因为我们之前已经使用过它们。因此,我不会详细介绍它们。取而代之的是,让我们回顾一下为什么我以某种方式对其进行了编码。

首先是我验证表格的方式。这里没有新内容。这只是标准的Laravel表单验证代码。但是为什么我用它代替Request类呢?这是因为Livewire的处理方式与Request类不兼容。基本上,Laravel Request类仅适用于标准HTTP请求。这意味着如果出现验证错误,它将把用户重定向到上一页。我们真的不能在Livewire中拥有它,因为一切都是通过AJAX完成的:

$validated = $this->validate([
    'name' => 'required|min:10',
    'email' => 'required|email|min:10',
    'age' => 'required|integer',
    'address' => 'required|min:10',]);

接下来是这段代码。在这里,我们使用emitTo()而不是emit()。这使不同组件可以通过事件相互通信。它接受组件名称作为第一个参数,接受事件名称作为第二个参数:

$this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);$this->emitTo('live-table', 'triggerRefresh');

当只能使用一个事件时,为什么要使用两个单独的事件(一个浏览器事件和一个Livewire事件)?是的,确实可以只使用一个事件。问题在于,一旦创建用户,我们还需要刷新数据表。我目前不知道从客户端触发重新加载特定组件的方法,这就是为什么我使用了两个单独的事件的原因-一个用于隐藏模式并显示警报,另一个用于刷新数据表。

现在您知道了代码背后的原因,让我们继续处理这些事件。将以下内容添加到resources/js/users.js文件中:

window.addEventListener("user-saved", (event) => {
    $("#user-modal").modal("hide");
    alert(`User ${event.detail.user_name} was ${event.detail.action}!`);});

然后在LiveTable组件类中,为添加侦听器triggerRefresh。这与delete侦听器有点不同,因为我们指向的$refresh是我们实际上不需要声明为类方法的函数。这是因为它是所有Livewire组件类的内置方法,可让我们重新加载整个组件:

// app/Http/Livewire/LiveTable.php
    protected $listeners = ['delete', 'triggerRefresh' => '$refresh'];

现在,您可以在浏览器上尝试创建用户。

更新现有用户

我们将要实现的功能的最后一部分是更新用户。使用以下命令更新resources/views/livewire/live-table.blade.php文件中的编辑按钮。由于我们位于LiveTable组件中,而编辑功能应该位于UserForm组件中,因此我们必须用来$emitTo()triggerEdit事件发送给UserForm组件。与之前不同,在这里我们只提供单个值,在这里我们提供整个user对象:

<td>
    <button class="btn btn-sm btn-dark" wire:click="$emitTo('user-form', 'triggerEdit', {{ $user }})">Edit</button></td>

要监听triggerEdit事件,请打开app/Http/Livewire/UserForm.php文件并添加以下内容。单个user对象被传递给该函数,我们使用它用值填充表单字段。请注意,您可以像访问数组一样访问单个字段,而不是对象。完成后,发出dataFetched事件:

protected $listeners = ['triggerEdit'];public function resetForm(){
    //}public function triggerEdit($user){
    $this->user_id = $user['id'];
    $this->name = $user['name'];
    $this->email = $user['email'];
    $this->age = $user['age'];
    $this->address = $user['address'];
    $this->emit('dataFetched', $user);}

dataFetched在客户端收听事件。由于我们已经在那一点上填入了各个字段,因此我们可以简单地打开模式:

// resources/js/users.jsLivewire.on("dataFetched", (user) => {
  $("#user-modal").modal("show");});

最后,更新save()UserForm组件类中的方法以同样处理更新。为此,请检查该user_id字段的值。如果具有值,则表示当前正在更新用户。否则,我们创建它:

// app/Http/Livewire/UserForm.phppublic function save(){
    $validated = $this->validate([
        'name' => 'required|min:10',
        'email' => 'required|email|min:10',
        'age' => 'required|integer',
        'address' => 'required|min:10',
    ]);
    if ($this->user_id) {
        User::find($this->user_id)
            ->update([
                'name' => $this->name,
                'email' => $this->email,
                'age' => $this->age,
                'address' => $this->address,
            ]);
        $this->dispatchBrowserEvent('user-saved', ['action' => 'updated', 'user_name' => $this->name]);
    } else {
        User::create(array_merge($validated, [
            'user_type' => 'user',
            'password' => bcrypt($this->email)
        ]));
        $this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);
    }
    $this->resetForm();
    $this->emitTo('live-table', 'triggerRefresh');}

现在,您可以在浏览器中尝试编辑用户详细信息。

最佳化

在本节中,我们将介绍一些您可以做的优化,以确保您的应用不会使用超出其所需资源的服务器。

搜索领域

您可能已经注意到,在搜索字段中键入内容几乎会立即触发AJAX请求,该请求会从服务器中提取更新的数据。每次都会向数据库发送查询,因此并不是很理想。默认情况下,Livewire将150ms的反跳应用于输入。我们希望增加该延迟,以便Livewire在用户仍在键入时不会将请求发送到服务器。下面的代码添加了800ms的反跳,因此会有明显的延迟。试一试此值,以确保达到完美的平衡:

<!-- resources/views/livewire/live-table.blade.php --><input wire:model.debounce.800ms="search">

表格栏位

我们可以做的另一个快速优化是更新用户表单中的表单字段。就像搜索字段一样,在您键入内容时,请求几乎立即发送到服务器。这次,我们使用延迟更新,而不是添加去抖动。仅当用户将焦点移到文本字段之外时,这才会向服务器发送请求:

<!-- resources/views/livewire/user-form.blade.php --><input wire:model.lazy="name">

结论

而已!在本教程中,您学习了使用Livewire来使Laravel应用更具动态性的基础知识,而无需编写大量JavaScript来获取数据并将其提交给服务器。

具体来说,我们构建了一个简单的CRUD应用程序,该应用程序使用Livewire消除了对诸如Datatables之类的前端程序包的实现表搜索和排序的需求。我们也消除了表单提交需要整页刷新的需要。最后,我们利用Livewire事件和浏览器事件来使前端和后端相互通信,而无需编写AJAX代码。


赞(0)
未经允许不得转载:工具盒子 » 前端开发库:教你Laravel Livewire入门