主题
组件
Livewire 组件本质上是具有属性和方法的 PHP 类,可以直接从 Blade 模板调用。这种强大的组合让你能够以现代 JavaScript 替代方案的一小部分努力和复杂性来创建全栈交互式界面。
本指南涵盖了创建、渲染和组织 Livewire 组件所需了解的所有内容。你将学习可用的不同组件格式(单文件、多文件和基于类的)、如何在组件之间传递数据,以及如何将组件用作完整页面。
创建组件
你可以使用 make:livewire Artisan 命令创建组件:
shell
php artisan make:livewire post.create这会在以下位置创建一个单文件组件:
resources/views/components/post/⚡create.blade.php
blade
<?php
use Livewire\Component;
new class extends Component {
public $title = '';
public function save()
{
// Save logic here...
}
};
?>
<div>
<input wire:model="title" type="text">
<button wire:click="save">Save Post</button>
</div>为什么使用 ⚡ 表情符号?
你可能对文件名中的闪电符号感到好奇。这个小细节有一个实际用途:它使 Livewire 组件在编辑器的文件树和搜索结果中立即可识别。由于它是一个 Unicode 字符,它可以在所有平台上无缝工作——Windows、macOS、Linux、Git 和你的生产服务器。
表情符号完全是可选的,如果你觉得不习惯,可以在 config/livewire.php 文件中完全禁用它:
php
'make_command' => [
'emoji' => false,
],创建页面组件
当创建将用作完整页面的组件时,使用 pages:: 命名空间将它们组织在专用目录中:
shell
php artisan make:livewire pages::post.create这会在 resources/views/pages/post/⚡create.blade.php 创建组件。这种组织方式使页面组件与可重用的 UI 组件清晰区分。
在下面的页面组件部分了解更多关于将组件用作页面的信息。你还可以注册自己的自定义命名空间——参见组件命名空间文档。
多文件组件
随着组件或项目的增长,你可能会发现单文件方法有局限性。Livewire 提供了一个多文件替代方案,将组件拆分为单独的文件以获得更好的组织和 IDE 支持。
要创建多文件组件,传递 --mfc 标志:
shell
php artisan make:livewire post.create --mfc这会创建一个包含所有相关文件的目录:
resources/views/components/post/⚡create/
├── create.php # PHP 类
├── create.blade.php # Blade 模板
├── create.js # JavaScript(可选)
├── create.css # 作用域样式(可选)
├── create.global.css # 全局样式(可选)
└── create.test.php # Pest 测试(可选,使用 --test 标志)在格式之间转换
Livewire 提供了 livewire:convert 命令来无缝地在单文件和多文件格式之间转换组件。
自动检测并转换:
shell
php artisan livewire:convert post.create
# 单文件 → 多文件(或反之)显式转换为多文件:
shell
php artisan livewire:convert post.create --mfc这将解析你的单文件组件,创建目录结构,拆分文件,并删除原始文件。
显式转换为单文件:
shell
php artisan livewire:convert post.create --sfc这会将所有文件合并回单个文件并删除目录。
转换为单文件时测试文件会被删除
如果你的多文件组件有测试文件,在转换前会提示你确认,因为测试文件无法在单文件格式中保留。
何时使用每种格式
单文件组件(默认):
- 最适合大多数组件
- 将相关代码放在一起
- 一目了然
- 适合小到中等规模的组件
多文件组件:
- 更适合大型复杂组件
- 改进的 IDE 支持和导航
- 当组件有大量 JavaScript 时分离更清晰
基于类的组件:
- 对 Livewire v2/v3 开发者熟悉
- 传统的 Laravel 关注点分离
- 更适合有既定约定的团队
- 参见下面的基于类的组件
渲染组件
你可以在任何 Blade 模板中使用 <livewire:component-name /> 语法包含 Livewire 组件:
blade
<livewire:component-name />如果组件位于子目录中,你可以使用点(.)字符表示:
resources/views/components/post/⚡create.blade.php
blade
<livewire:post.create />对于命名空间组件——如 pages::——使用命名空间前缀:
blade
<livewire:pages::post.create />传递 Props
要向 Livewire 组件传递数据,你可以在组件标签上使用 prop 属性:
blade
<livewire:post.create title="Initial Title" />对于动态值或变量,在属性前加冒号前缀:
blade
<livewire:post.create :title="$initialTitle" />传入组件的数据通过 mount() 方法接收:
php
<?php
use Livewire\Component;
new class extends Component {
public $title;
public function mount($title = null)
{
$this->title = $title;
}
// ...
};你可以将 mount() 方法看作类构造函数。它在组件初始化时运行,但不会在页面会话中的后续请求时运行。你可以在生命周期文档中了解更多关于 mount() 和其他有用的生命周期钩子。
为了减少样板代码,你可以省略 mount() 方法,Livewire 会自动设置与传入值名称匹配的任何属性:
php
<?php
use Livewire\Component;
new class extends Component {
public $title; // 自动从 prop 设置
// ...
};这些属性默认不是响应式的
如果外部的 :title="$initialValue" 在初始页面加载后改变,$title 属性不会自动更新。这是使用 Livewire 时常见的困惑点,特别是对于使用过 Vue 或 React 等 JavaScript 框架的开发者,他们会假设这些参数像那些框架中的"响应式 props"一样工作。但是,不用担心,Livewire 允许你选择使你的 props 响应式。
将路由参数作为 Props 传递
当将组件用作页面时,你可以直接将路由参数传递给组件。路由参数会自动传递给 mount() 方法:
php
Route::livewire('/posts/{id}', 'pages::post.show');php
<?php // resources/views/pages/post/⚡show.blade.php
use Livewire\Component;
new class extends Component {
public $postId;
public function mount($id)
{
$this->postId = $id;
}
};Livewire 也支持 Laravel 的路由模型绑定:
php
Route::livewire('/posts/{post}', 'pages::post.show');php
<?php // resources/views/pages/post/⚡show.blade.php
use App\Models\Post;
use Livewire\Component;
new class extends Component {
public Post $post; // 自动从路由绑定
// 不需要 mount() - Livewire 自动处理
};页面组件
组件可以使用 Route::livewire() 直接作为完整页面路由。这是 Livewire 最强大的功能之一,允许你在没有传统控制器的情况下构建完整页面。
php
Route::livewire('/posts/create', 'pages::post.create');当用户访问 /posts/create 时,Livewire 将在你应用程序的布局文件中渲染 pages::post.create 组件。
页面组件的工作方式与常规组件相同,但它们作为完整页面渲染,可以访问:
- 自定义布局
- 页面标题
- 路由参数和模型绑定
- 布局的具名插槽
有关页面组件的完整信息,包括布局、标题和高级路由,请参阅页面文档。
在视图中访问数据
Livewire 提供了多种方式将数据传递给组件的 Blade 视图。每种方法都有不同的性能和安全特性。
组件属性
最简单的方法是使用公共属性,它们在 Blade 模板中自动可用:
php
<?php
use Livewire\Component;
new class extends Component {
public $title = 'My Post';
};blade
<div>
<h1>{{ $title }}</h1>
</div>受保护的属性必须使用 $this-> 访问:
php
public $title = 'My Post'; // 可作为 {{ $title }} 访问
protected $apiKey = 'secret-key'; // 可作为 {{ $this->apiKey }} 访问受保护的属性不会发送到客户端
与公共属性不同,受保护的属性永远不会发送到前端,用户无法操作它们。这使它们对于敏感数据是安全的。但是,它们在请求之间不会持久化,这限制了它们在大多数 Livewire 场景中的用途。它们最适合用于你不想暴露给客户端的属性声明中定义的静态值。
有关属性的完整信息,包括持久化行为和高级功能,请参阅属性文档。
计算属性
计算属性是作为记忆化属性的方法。它们非常适合数据库查询等昂贵操作:
php
use Livewire\Attributes\Computed;
#[Computed]
public function posts()
{
return Post::with('author')->latest()->get();
}blade
<div>
@foreach ($this->posts as $post)
<article wire:key="{{ $post->id }}">{{ $post->title }}</article>
@endforeach
</div>注意 $this-> 前缀——这告诉 Livewire 调用方法并仅在当前请求期间缓存结果(不会在请求之间缓存)。更多详情,请参阅属性文档中的计算属性部分。
从 render() 传递数据
类似于控制器,你可以使用 render() 方法直接将数据传递给视图:
php
public function render()
{
return $this->view([
'author' => Auth::user(),
'currentTime' => now(),
]);
}请记住 render() 在每次组件更新时都会运行,所以除非你需要在每次更新时获取新数据,否则避免在这里进行昂贵的操作。
组织组件
虽然 Livewire 自动在默认的 resources/views/components/ 目录中发现组件,但你可以自定义 Livewire 查找组件的位置并使用命名空间组织它们。
组件命名空间
组件命名空间允许你将组件组织到专用目录中,并使用干净的引用语法。
默认情况下,Livewire 提供两个命名空间:
pages::— 指向resources/views/pages/layouts::— 指向resources/views/layouts/
你可以在 config/livewire.php 文件中定义额外的命名空间:
php
'component_namespaces' => [
'layouts' => resource_path('views/layouts'),
'pages' => resource_path('views/pages'),
'admin' => resource_path('views/admin'), // 自定义命名空间
'widgets' => resource_path('views/widgets'), // 另一个自定义命名空间
],然后在创建、渲染和路由时使用它们:
shell
php artisan make:livewire admin::users-tableblade
<livewire:admin::users-table />php
Route::livewire('/admin/users', 'admin::users-table');额外的组件位置
如果你想让 Livewire 在默认目录之外的额外目录中发现组件,你可以在 config/livewire.php 文件中配置它们:
php
'component_locations' => [
resource_path('views/components'),
resource_path('views/admin/components'),
resource_path('views/widgets'),
],现在 Livewire 将自动在所有这些目录中发现组件。
编程式注册
对于更动态的场景(如包开发或运行时配置),你可以在服务提供者中以编程方式注册组件、位置和命名空间:
注册单个组件:
php
use Livewire\Livewire;
// 在服务提供者的 boot() 方法中(例如 App\Providers\AppServiceProvider)
Livewire::addComponent(
name: 'custom-button',
viewPath: resource_path('views/ui/button.blade.php')
);注册组件目录:
php
Livewire::addLocation(
viewPath: resource_path('views/admin/components')
);注册命名空间:
php
Livewire::addNamespace(
namespace: 'ui',
viewPath: resource_path('views/ui')
);当你需要有条件地注册组件或构建提供 Livewire 组件的 Laravel 包时,这种方法很有用。
注册基于类的组件
对于基于类的组件,使用相同的方法,但使用 class 参数而不是 path:
php
use Livewire\Livewire;
// 在服务提供者的 boot() 方法中(例如 App\Providers\AppServiceProvider)
// 注册单个基于类的组件
Livewire::addComponent(
name: 'todos',
class: \App\Livewire\Todos::class
);
// 注册基于类的组件位置
Livewire::addLocation(
classNamespace: 'App\\Admin\\Livewire'
);
// 为基于类的组件创建命名空间
Livewire::addNamespace(
namespace: 'admin',
classNamespace: 'App\\Admin\\Livewire',
classPath: app_path('Admin/Livewire'),
classViewPath: resource_path('views/admin/livewire')
);基于类的组件
对于从 Livewire v3 迁移的团队或喜欢更传统 Laravel 结构的团队,Livewire 完全支持基于类的组件。这种方法将 PHP 类和 Blade 视图分离到它们常规位置的不同文件中。
创建基于类的组件
shell
php artisan make:livewire CreatePost --class这会创建两个单独的文件:
app/Livewire/CreatePost.php
php
<?php
namespace App\Livewire;
use Livewire\Component;
class CreatePost extends Component
{
public function render()
{
return view('livewire.create-post');
}
}resources/views/livewire/create-post.blade.php
blade
<div>
{{-- ... --}}
</div>何时使用基于类的组件
在以下情况使用基于类的组件:
- 从 Livewire v2/v3 迁移
- 你的团队喜欢更传统的文件结构
- 你有围绕基于类架构的既定约定
在以下情况使用单文件或多文件组件:
- 开始新的 Livewire v4 项目
- 你想要更好的组件集中化
- 你想使用最新的 Livewire 约定
配置默认组件类型
如果你想默认使用基于类的组件,在 config/livewire.php 中配置:
php
'make_command' => [
'type' => 'class',
],自定义组件模板
你可以通过运行以下命令自定义 Livewire 用于生成新组件的文件(或称为 stubs):
shell
php artisan livewire:stubs这会在你的应用程序中创建你可以修改的 stub 文件:
单文件组件 stubs:
stubs/livewire-sfc.stub— 单文件组件
多文件组件 stubs:
stubs/livewire-mfc-class.stub— 多文件组件的 PHP 类stubs/livewire-mfc-view.stub— 多文件组件的 Blade 视图stubs/livewire-mfc-js.stub— 多文件组件的 JavaScriptstubs/livewire-mfc-test.stub— 多文件组件的 Pest 测试
基于类的组件 stubs:
stubs/livewire.stub— 基于类组件的 PHP 类stubs/livewire.view.stub— 基于类组件的 Blade 视图
额外 stubs:
stubs/livewire.attribute.stub— 属性类stubs/livewire.form.stub— 表单类
发布后,Livewire 在生成新组件时将自动使用你的自定义 stubs。
故障排除
组件未找到
症状: 错误消息如"Component [post.create] not found"或"Unable to find component"
解决方案:
- 验证组件文件位于预期路径
- 检查视图中的组件名称是否与文件结构匹配(子目录使用点)
- 对于命名空间组件,确保命名空间在
config/livewire.php中定义或在服务提供者中手动注册 - 尝试清除视图缓存:
php artisan view:clear
组件显示空白或不渲染
常见原因:
- Blade 模板中缺少根元素(Livewire 要求恰好一个根元素)
- 组件 PHP 部分存在语法错误
- 检查 Laravel 日志获取详细错误消息
类名冲突
症状: 使用单文件组件时出现关于重复类名的错误
解决方案: 如果你在不同目录中有多个同名的单文件组件,可能会发生这种情况。解决方案:
- 重命名其中一个组件使其唯一
- 为其中一个目录添加命名空间以获得更清晰的分离