Laravel Livewire 入门
作为开发人员,我们一直在寻找能让我们的生活更轻松的工具、库和框架。 Laravel 开发者也不例外。 这就是我们喜欢这个框架的原因,因为一切对我们来说都很容易——让我们专注于构建很棒的应用程序,而不是陷入如何实现的困境。
在本教程中,我们将研究另一个可以让 Laravel 开发人员的生活更轻松的工具。 具体来说,我们将研究 Livewire,它是 Laravel 的全栈框架,允许我们构建动态界面而无需编写大量 JavaScript。 作为 Laravel 开发人员,一切基本上都是使用您已经熟悉的工具完成的。
什么是活线?
Livewire 是一个库,它允许我们使用 Blade 和一点点 JavaScript 构建反应式和动态界面。 我说“一点点”是因为我们只打算编写 JavaScript 来通过浏览器事件传递数据并响应它们。
您可以使用 Livewire 实现以下功能,而无需重新加载页面:
- 分页表单验证通知文件上传预览
请注意,Livewire 不限于上述功能。 您可以将它用于更多用途。 上述功能只是您可能希望在您的应用程序中实现的最常见功能。
Livewire 与 Vue
Vue 一直是 Laravel 开发人员向其应用程序添加交互性的首选前端框架。 如果您已经在使用 Vue 为您的应用程序提供动力,Livewire 是您学习的可选项目。 但是,如果您对在 Laravel 中做前端相当陌生,并且您正在寻找 Livewire 作为 Vue 的替代品,那么是的,您可以使用 Livewire 作为 Vue 的替代品。 学习曲线不会像学习 Vue 那样陡峭,因为您将主要使用 Blade 来编写模板文件。
有关 Livewire 和 Vue 如何比较的更多信息,请查看“Laravel Livewire vs Vue”。
应用概览
我们将创建一个实时 CRUD 应用程序。 所以它基本上是一个没有页面重新加载的 CRUD 应用程序。 Livewire 将处理更新 UI 所需的所有 AJAX 请求。 这包括通过搜索字段过滤结果、通过列标题排序以及简单的分页(上一页和下一页)。 创建和编辑用户将使用 Bootstrap Modals。
您可以在其 GitHub 存储库上查看该项目的源代码。
先决条件
本教程假定您具有 PHP 应用程序开发经验。 有 Laravel 经验会有所帮助,但不是必需的。 如果您只了解普通 PHP 或其他 PHP 框架,您仍然可以继续学习。
本教程假定您的计算机上安装了以下软件:
- PHP MySQL NGINX Composer 节点和 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.php
public 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.php
public 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.php
public function run()
{
AppModelsUser::factory(100)->create();
}
不要忘记更新你的 .env
包含您将要使用的测试数据库的文件。 在这种情况下,我将数据库命名为 livecrud
. 完成后,运行迁移和播种器以填充数据库:
php artisan migrate
php artisan db:seed
设置前端依赖
为了简化事情,我们将为 Bootstrap 使用 Laravel 脚手架。 要使用它,您首先需要安装 laravel/ui
包裹:
composer require laravel/ui
接下来,安装 Bootstrap 4。这会将配置添加到您的 webpack.mix.js
文件并创建 resources/js/app.js
和 resources/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 "[email protected]/fontawesome-free/scss/fontawesome";
@import "[email protected]/fontawesome-free/scss/brands";
@import "[email protected]/fontawesome-free/scss/regular";
@import "[email protected]/fontawesome-free/scss/solid";
完成后,安装所有依赖项:
npm install @fortawesome/fontawesome-free
npm 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
<?php
class LiveTable extends Component
{
public $search = ''; // don't add this yet
}
接下来,我们有表头。 这里我们使用 wire:click.prevent
监听链接元素中的点击事件。 这些在 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.php
public 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
文件并更新它,使其包含以下代码:
<?php
namespace AppHttpLivewire;
use LivewireComponent;
use LivewireWithPagination;
use AppModelsUser;
class LiveTable extends Component
{
use...