跳转到主要内容

什么是 Livewire

在 Laravel 里做动态 UI 时,过去只能搭配 Vue.js、React 这样的 JavaScript 框架,或者自己写 AJAX 请求。 Livewire 就是为解决这个问题而生的 Laravel 包。只用 PHP 和 Blade 就能构建响应式 UI。表单实时校验、实时搜索、计数器等以前必须用 JavaScript 实现的功能,现在都可以用 PHP 完成。
Livewire 4 需要 Laravel 10 及以上、PHP 8.1 及以上。当前最新版本是 Livewire 4。

工作原理概览

一个 Livewire 组件由服务器端的 PHP 类和 Blade 模板组成。当用户点击按钮或在表单里输入时,Livewire 会在幕后发送 AJAX 请求、执行 PHP,并只把发生变化的部分反映到页面上。开发者不必关心这一机制,用纯 PHP 就能写出来。

安装

在 Laravel 应用根目录执行:
composer require livewire/livewire
Laravel 会自动发现包,不需要额外配置。

创建布局文件

作为整页组件使用时,需要一个布局文件。用下面的 Artisan 命令生成:
php artisan livewire:layout
会生成 resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>{{ $title ?? config('app.name') }}</title>

        @vite(['resources/css/app.css', 'resources/js/app.js'])

        @livewireStyles
    </head>
    <body>
        {{ $slot }}

        @livewireScripts
    </body>
</html>
@livewireStyles@livewireScripts 会自动加载 Livewire 与 Alpine.js 的资源。

第一个组件

有专门用来生成 Livewire 组件的 Artisan 命令。先做一个简单的计数器。
php artisan make:livewire Counter
这条命令会生成一个单文件组件 resources/views/components/⚡counter.blade.php
文件名里的 ⚡ 用来一眼识别出 Livewire 组件,在编辑器里更醒目。不需要的话可以在配置里关掉。
把生成的文件按下面的方式改写:
<?php

use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }

    public function decrement(): void
    {
        $this->count--;
    }
};
?>

<div>
    <h1>计数:{{ $count }}</h1>

    <button wire:click="increment">+1</button>
    <button wire:click="decrement">-1</button>
</div>
在 Blade 模板中通过普通的 Blade 组件语法嵌入它:
<livewire:counter />
每次点击按钮,页面不用刷新就能更新计数。wire:click 就是取代 JavaScript,直接调用 PHP 方法的机制。

属性与动作

属性 —— wire:model

wire:model 指令可以把输入元素和组件的属性做双向绑定。
<?php

use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';
};
?>

<div>
    <input type="text" wire:model="name" placeholder="姓名">
    <input type="email" wire:model="email" placeholder="邮箱">

    <p>你好,{{ $name }} ({{ $email }})</p>
</div>
默认情况下,wire:model 只在有动作发生时(比如表单提交)才和服务器同步。想每次输入都同步,加 .live 修饰符。
写法行为
wire:model只在动作(如表单提交)时同步(默认)
wire:model.live每次输入都发送请求
wire:model.blur失焦时同步(不发起请求)
wire:model.live.blur失焦时发送请求

动作 —— wire:clickwire:submit

wire:click 把点击事件、wire:submit 把表单提交事件绑定到方法上。
<?php

use Livewire\Component;
use App\Models\Task;

new class extends Component {
    public string $taskName = '';

    public function addTask(): void
    {
        Task::create(['name' => $this->taskName]);
        $this->taskName = '';
    }

    public function render()
    {
        return $this->view([
            'tasks' => Task::latest()->get(),
        ]);
    }
};
?>

<div>
    <form wire:submit="addTask">
        <input type="text" wire:model="taskName" placeholder="任务名">
        <button type="submit">添加</button>
    </form>

    <ul>
        @foreach ($tasks as $task)
            <li>{{ $task->name }}</li>
        @endforeach
    </ul>
</div>

实时校验

Livewire 4 可以通过 #[Validate] 属性直接为属性定义验证规则。
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\Post;

new class extends Component {
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function save(): void
    {
        $this->validate();

        Post::create([
            'title' => $this->title,
            'content' => $this->content,
        ]);

        $this->reset(['title', 'content']);

        session()->flash('message', '文章已保存。');
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <div>
            <input type="text" wire:model.live.blur="title" placeholder="标题">
            @error('title') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <div>
            <textarea wire:model.live.blur="content" placeholder="正文"></textarea>
            @error('content') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <button type="submit">保存</button>
    </form>
</div>
#[Validate] 标注的属性每次更新时会自动执行校验。结合 wire:model.live.blur 可以做出“失焦瞬间显示错误信息”的实时校验体验。
$this->validate() 会在表单提交时一次性校验所有属性。推荐的做法是把它和 #[Validate] 的自动校验组合成两级校验。

生命周期钩子

Livewire 组件有几个生命周期钩子。
钩子时机
mount()组件首次创建时(仅一次)
boot()每次请求开始时(首次与后续请求都会调用)
updating($property, $value)属性即将更新前
updated($property)属性更新后
rendering()视图渲染前
rendered()视图渲染后
dehydrate()每次请求结束时

mount() —— 初始化

mount() 用于组件初始化,类似构造函数。
<?php

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';

    public function mount(): void
    {
        $this->name = Auth::user()->name;
        $this->email = Auth::user()->email;
    }
};
?>

<div>
    <p>姓名:{{ $name }}</p>
    <p>邮箱:{{ $email }}</p>
</div>

updated() —— 属性变更后的处理

想在属性更新后加一段逻辑时用 updated()。想只针对特定属性时,把属性名放到方法名里。
<?php

use Livewire\Component;

new class extends Component {
    public string $username = '';

    public function updatedUsername(): void
    {
        $this->username = strtolower($this->username);
    }
};
?>

<div>
    <input type="text" wire:model.live="username">
    <p>用户名:{{ $username }}</p>
</div>
每次输入都会自动转成小写。

与 Laravel 的集成

直接使用 Eloquent 模型

Livewire 的属性可以直接持有 Eloquent 模型。
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\User;

new class extends Component {
    public User $user;

    public function mount(User $user): void
    {
        $this->user = $user;
    }

    #[Validate('required|min:2')]
    public string $name = '';

    public function save(): void
    {
        $this->validate();
        $this->user->update(['name' => $this->name]);
        session()->flash('message', '资料已更新。');
    }

    public function render()
    {
        return $this->view();
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <input type="text" wire:model="name" placeholder="姓名">
        @error('name') <span style="color: red;">{{ $message }}</span> @enderror
        <button type="submit">更新</button>
    </form>
</div>

表单对象

复杂表单可以拆到表单对象里,让组件更简洁。
php artisan livewire:form PostForm
namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;
use App\Models\Post;

class PostForm extends Form
{
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function store(): void
    {
        Post::create($this->only(['title', 'content']));
    }
}
在组件里用这个表单对象。
<?php

use App\Livewire\Forms\PostForm;
use Livewire\Component;

new class extends Component {
    public PostForm $form;

    public function save(): void
    {
        $this->form->validate();
        $this->form->store();
        $this->form->reset();
        session()->flash('message', '已创建文章。');
    }
};
?>

<div>
    <form wire:submit="save">
        <input type="text" wire:model="form.title" placeholder="标题">
        @error('form.title') <span style="color: red;">{{ $message }}</span> @enderror

        <textarea wire:model="form.content" placeholder="正文"></textarea>
        @error('form.content') <span style="color: red;">{{ $message }}</span> @enderror

        <button type="submit">发布</button>
    </form>
</div>

总结

Livewire 特别适合的用例:
用例Livewire 能做什么
表单处理实时校验、错误提示
数据列表实时搜索、排序、分页
计数器 / 开关页面不刷新的 UI 更新
管理后台直接对接 Eloquent 完成 CRUD
向导型表单步骤管理用 PHP 实现
只要你用过 Blade,今天就能开始用 Livewire。它最大的优势是:不必学习 JavaScript 框架就能构建交互式 UI。 需要接近 SPA 的复杂交互时 Inertia.js 更合适;但表单、后台、数据表格这类场景下,Livewire 通常能以更简洁的方式搞定。先从一个小组件开始试试吧。

Livewire 官方文档

Livewire 的完整功能(文件上传、分页、测试等)请查看官方文档。
最后修改于 2026年7月13日