Skip to content
全部文档

组件

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>

INFO

为什么文件名里有 ⚡ 表情?

你可能对文件名中的闪电符号感到好奇。这个小细节有实际用途:它让 Livewire 组件在编辑器的文件树和搜索结果中一眼可辨。因为它是 Unicode 字符,在 Windows、macOS、Linux、Git 以及生产服务器等所有平台上都能无缝工作。

表情符号完全可选;若觉得不习惯,可以在 config/livewire.php 中彻底关闭:

php
'make_command' => [
    'emoji' => false,
],

TIP

更偏好 v3 约定?

若你更喜欢 v3 的基于类的组件,可以在 config/livewire.php 中用两行配置恢复以前的默认行为:

php
'make_command' => [
    'type' => 'class',
    '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

这会创建一个目录,并把所有相关文件放在一起:

text
resources/views/components/post/⚡create/
├── create.php          # PHP class
├── create.blade.php    # Blade template
├── create.js           # JavaScript (optional)
├── create.css          # Scoped styles (optional)
├── create.global.css   # Global styles (optional)
└── create.test.php     # Pest test (optional, with --test flag)

命令选项

make:livewire 命令接受以下选项:

Option说明
--sfc创建单文件组件(默认)
--mfc创建多文件组件
--class创建基于类的组件
--type=sfc|mfc|class显式指定组件类型
--emoji=true|false覆盖本次命令的配置项 emoji 设置
--test包含 Pest 测试文件
--js包含 JavaScript 文件(仅多文件组件)
--css包含 CSS 文件(仅多文件组件)

在格式之间转换

Livewire 提供 livewire:convert 命令,可在单文件与多文件格式之间无缝转换组件。

自动检测并转换:

shell
php artisan livewire:convert post.create
# Single-file → Multi-file (or vice versa)

显式转换为多文件:

shell
php artisan livewire:convert post.create --mfc

这会解析你的单文件组件,创建目录结构,拆分文件,并删除原文件。

显式转换为单文件:

shell
php artisan livewire:convert post.create --sfc

这会把所有文件合并回单个文件,并删除该目录。

WARNING

转换为单文件时会删除测试文件

若多文件组件带有测试文件,转换前会提示你确认,因为单文件格式无法保留测试文件。

何时使用各格式

单文件组件(默认):

  • 适合大多数组件
  • 把相关代码放在一起
  • 一眼就能看懂
  • 适合中小型组件

多文件组件:

  • 更适合大型、复杂的组件
  • 更好的 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 />

文件路径如何映射到组件名

无论使用哪种格式(单文件、多文件或基于类),在 Blade 标签和路由中使用的组件名始终相同。⚡ 表情前缀和文件结构会自动剥离:

格式文件路径组件名
单文件resources/views/components/post/⚡create.blade.phppost.create
多文件resources/views/components/post/⚡create/create.phppost.create
基于类app/Livewire/Post/Create.phppost.create
单文件(命名空间)resources/views/pages/post/⚡create.blade.phppages::post.create
多文件(命名空间)resources/views/pages/post/⚡create/create.phppages::post.create

这意味着你可以在格式之间切换,而无需修改任何 Blade 模板或路由。

传递 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; // Automatically set from prop

    // ...
};

WARNING

这些属性默认不是响应式的

若外层的 :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; // Automatically bound from route

    // No mount() needed - Livewire handles it automatically
};

页面组件

可以使用 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';           // Available as {{ $title }}
protected $apiKey = 'secret-key';    // Available as {{ $this->apiKey }}

INFO

受保护属性不会发送到客户端

与公共属性不同,受保护属性绝不会发送到前端,也无法被用户篡改,因此适合存放敏感数据。不过它们不会在请求之间持久化,这限制了它们在多数 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'),    // Custom namespace
    'widgets' => resource_path('views/widgets'), // Another custom namespace
],

然后在创建、渲染和路由时使用它们:

shell
php artisan make:livewire admin::users-table
blade
<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;

// In a service provider's boot() method (e.g., 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;

// In a service provider's boot() method (e.g., App\Providers\AppServiceProvider)

// Register an individual class-based component
Livewire::addComponent(
    name: 'todos',
    class: \App\Livewire\Todos::class
);

// Register a location for class-based components
Livewire::addLocation(
    classNamespace: 'App\\Admin\\Livewire'
);

// Create a namespace for class-based components
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 项目
  • 希望组件代码更好地同置(colocation)
  • 希望采用最新的 Livewire 约定

配置默认组件类型

若希望默认使用基于类的组件,在 config/livewire.php 中配置:

php
'make_command' => [
    'type' => 'class',
],

自定义组件 stub

你可以自定义 Livewire 用于生成新组件的文件(或 stub),运行:

shell
php artisan livewire:stubs

这会在应用中创建可修改的 stub 文件:

单文件组件 stub:

  • stubs/livewire-sfc.stub — 单文件组件

多文件组件 stub:

  • stubs/livewire-mfc-class.stub — 多文件组件的 PHP 类
  • stubs/livewire-mfc-view.stub — 多文件组件的 Blade 视图
  • stubs/livewire-mfc-js.stub — 多文件组件的 JavaScript
  • stubs/livewire-mfc-test.stub — 多文件组件的 Pest 测试

基于类的组件 stub:

  • stubs/livewire.stub — 基于类组件的 PHP 类
  • stubs/livewire.view.stub — 基于类组件的 Blade 视图

其他 stub:

  • stubs/livewire.attribute.stub — Attribute 类
  • stubs/livewire.form.stub — Form 类

发布后,Livewire 在生成新组件时会自动使用你的自定义 stub。

排错

找不到组件

症状: 出现类似 "Component [post.create] not found" 或 "Unable to find component" 的错误信息

解决办法:

  • 确认组件文件存在于预期路径
  • 检查视图中的组件名是否与文件结构匹配(子目录用点号)
  • 对于带命名空间的组件,确保命名空间已在 config/livewire.php 中定义,或已在服务提供者中手动注册
  • 尝试清除视图缓存:php artisan view:clear

组件显示空白或不渲染

常见原因:

  • Blade 模板缺少根元素(Livewire 要求恰好一个根元素)
  • 组件 PHP 部分存在语法错误
  • 查看 Laravel 日志获取详细错误信息

类名冲突

症状: 使用单文件组件时出现关于重复类名的错误

解决办法: 若在不同目录中有多个同名单文件组件,就可能出现此问题。可以:

  • 将其中一个组件重命名为唯一名称
  • 为其中一个目录添加命名空间,以更清晰地隔离

另请参阅

  • 属性管理组件状态与数据
  • 操作用方法处理用户交互
  • 页面通过路由把组件用作完整页面
  • 嵌套组合组件并在其间传递数据
  • 生命周期钩子在组件生命周期的特定时机执行代码