Skip to content

wire:model

Livewire 通过 wire:model 让组件属性值与表单输入的绑定变得非常简单。

这是一个在"创建文章"组件中使用 wire:model 绑定 $title$content 属性与表单输入的简单示例:

php
use Livewire\Component;
use App\Models\Post;

class CreatePost extends Component
{
    public $title = '';

    public $content = '';

    public function save()
    {
		$post = Post::create([
			'title' => $this->title
			'content' => $this->content
		]);

        // ...
    }
}
blade
<form wire:submit="save">
    <label>
        <span>Title</span>

        <input type="text" wire:model="title"> <!-- [tl! highlight] -->
    </label>

    <label>
        <span>Content</span>

        <textarea wire:model="content"></textarea> <!-- [tl! highlight] -->
    </label>

	<button type="submit">Save</button>
</form>

因为两个输入都使用了 wire:model,当按下"Save"按钮时,它们的值将与服务器的属性同步。

"为什么我的组件在输入时没有实时更新?"

如果你在浏览器中尝试这个示例,并对标题为什么没有自动更新感到困惑,那是因为 Livewire 只在提交"操作"时更新组件——比如按下提交按钮——而不是在用户输入字段时。这减少了网络请求并提高了性能。要启用用户输入时的"实时"更新,你可以改用 wire:model.live了解更多关于数据绑定

自定义更新时机

默认情况下,Livewire 只在执行操作时发送网络请求(如 wire:clickwire:submit),而不是在 wire:model 输入更新时。

这通过减少网络请求大大提高了 Livewire 的性能,并为用户提供更流畅的体验。

然而,有时你可能希望更频繁地更新服务器,例如实时验证。

实时更新

要在用户在输入字段中输入时将属性更新发送到服务器,你可以在 wire:model 后添加 .live 修饰符:

html
<input type="text" wire:model.live="title">

自定义防抖

默认情况下,使用 wire:model.live 时,Livewire 会为服务器更新添加 150 毫秒的防抖。这意味着如果用户持续输入,Livewire 将等到用户停止输入 150 毫秒后才发送请求。

你可以通过在输入中添加 .debounce.Xms 来自定义此时间。这是一个将防抖更改为 250 毫秒的示例:

html
<input type="text" wire:model.live.debounce.250ms="title">

在 "blur" 事件时更新

通过添加 .blur 修饰符,Livewire 将仅在用户点击离开输入框或按 Tab 键移动到下一个输入框时发送带有属性更新的网络请求。

添加 .blur 对于希望更频繁更新服务器但不是在用户输入时的场景很有帮助。例如,实时验证是 .blur 常用的场景。

html
<input type="text" wire:model.blur="title">

在 "change" 事件时更新

有时 .blur 的行为并不完全符合你的需求,而 .change 可能更合适。

例如,如果你想在每次选择输入更改时运行验证,通过添加 .change,Livewire 将在用户选择新选项后立即发送网络请求并验证属性。相比之下,.blur 只会在用户从选择输入 Tab 离开后更新服务器。

html
<select wire:model.change="title">
    <!-- ... -->
</select>

对文本输入所做的任何更改都将自动与 Livewire 组件中的 $title 属性同步。

输入字段

Livewire 开箱即用地支持大多数原生输入元素。这意味着你只需将 wire:model 附加到浏览器中的任何输入元素,就可以轻松将属性绑定到它们。

这是不同可用输入类型及其在 Livewire 中使用方式的完整列表。

文本输入

首先,文本输入是大多数表单的基础。以下是如何将名为 "title" 的属性绑定到它:

blade
<input type="text" wire:model="title">

文本域输入

文本域元素同样简单。只需将 wire:model 添加到文本域,值就会被绑定:

blade
<textarea type="text" wire:model="content"></textarea>

如果 "content" 值初始化为字符串,Livewire 将用该值填充文本域——无需做类似以下的操作:

blade
<!-- 警告:此代码片段演示的是不应该做的事... -->

<textarea type="text" wire:model="content">{{ $content }}</textarea>

复选框

复选框可用于单个值,例如切换布尔属性。或者,复选框可用于在一组相关值中切换单个值。我们将讨论这两种场景:

单个复选框

在注册表单的末尾,你可能有一个允许用户选择接收电子邮件更新的复选框。你可以将此属性称为 $receiveUpdates。你可以使用 wire:model 轻松将此值绑定到复选框:

blade
<input type="checkbox" wire:model="receiveUpdates">

现在当 $receiveUpdates 值为 false 时,复选框将被取消选中。当然,当值为 true 时,复选框将被选中。

多个复选框

现在,假设除了允许用户决定是否接收更新外,你的类中还有一个名为 $updateTypes 的数组属性,允许用户从各种更新类型中选择:

php
public $updateTypes = [];

通过将多个复选框绑定到 $updateTypes 属性,用户可以选择多种更新类型,它们将被添加到 $updateTypes 数组属性中:

blade
<input type="checkbox" value="email" wire:model="updateTypes">
<input type="checkbox" value="sms" wire:model="updateTypes">
<input type="checkbox" value="notification" wire:model="updateTypes">

例如,如果用户选中前两个复选框但不选中第三个,$updateTypes 的值将是:["email", "sms"]

单选按钮

要在单个属性的两个不同值之间切换,你可以使用单选按钮:

blade
<input type="radio" value="yes" wire:model="receiveUpdates">
<input type="radio" value="no" wire:model="receiveUpdates">

下拉选择框

Livewire 使 <select> 下拉框的使用变得简单。当向下拉框添加 wire:model 时,当前选中的值将绑定到提供的属性名,反之亦然。

此外,无需手动为将被选中的选项添加 selected——Livewire 会自动为你处理。

以下是一个用静态州列表填充的选择下拉框示例:

blade
<select wire:model="state">
    <option value="AL">Alabama</option>
    <option value="AK">Alaska</option>
    <option value="AZ">Arizona</option>
    ...
</select>

当选择特定的州时,例如 "Alaska",组件上的 $state 属性将被设置为 AK。如果你希望值设置为 "Alaska" 而不是 "AK",你可以完全省略 <option> 元素上的 value="" 属性。

通常,你可能会使用 Blade 动态构建下拉选项:

blade
<select wire:model="state">
    @foreach (\App\Models\State::all() as $state)
        <option value="{{ $state->id }}">{{ $state->label }}</option>
    @endforeach
</select>

如果你没有默认选择的特定选项,你可能希望默认显示一个灰色的占位符选项,例如 "Select a state":

blade
<select wire:model="state">
    <option disabled value="">Select a state...</option>

    @foreach (\App\Models\State::all() as $state)
        <option value="{{ $state->id }}">{{ $state->label }}</option>
    @endforeach
</select>

如你所见,选择菜单没有像文本输入那样的 "placeholder" 属性。相反,你必须将 disabled 选项元素添加为列表中的第一个选项。

依赖下拉选择框

有时你可能希望一个选择菜单依赖于另一个。例如,根据选择的州更改的城市列表。

大多数情况下,这会按你预期的方式工作,但有一个重要的注意事项:你必须为变化的选择框添加 wire:key,以便 Livewire 在选项更改时正确刷新其值。

这是两个选择框的示例,一个用于州,一个用于城市。当州选择框更改时,城市选择框中的选项将正确更改:

blade
<!-- 州选择菜单... -->
<select wire:model.live="selectedState">
    @foreach (State::all() as $state)
        <option value="{{ $state->id }}">{{ $state->label }}</option>
    @endforeach
</select>

<!-- 城市依赖选择菜单... -->
<select wire:model.live="selectedCity" wire:key="{{ $selectedState }}"> <!-- [tl! highlight] -->
    @foreach (City::whereStateId($selectedState->id)->get() as $city)
        <option value="{{ $city->id }}">{{ $city->label }}</option>
    @endforeach
</select>

同样,这里唯一非标准的是添加到第二个选择框的 wire:key。这确保当州更改时,"selectedCity" 值将被正确重置。

多选下拉框

如果你使用"多选"选择菜单,Livewire 会按预期工作。在此示例中,当选择州时,它们将被添加到 $states 数组属性中,如果取消选择则会被移除:

blade
<select wire:model="states" multiple>
    <option value="AL">Alabama</option>
    <option value="AK">Alaska</option>
    <option value="AZ">Arizona</option>
    ...
</select>

事件传播

默认情况下,wire:model 只监听直接源自元素本身的 input/change 事件,而不是从子元素冒泡上来的事件。这可以防止在容器元素(如包含其他表单输入的模态框或折叠面板)上使用 wire:model 时出现意外行为。

例如,如果你有一个带有 wire:model="showModal" 的模态框,里面有一个输入字段,清除该输入不会因为 change 事件冒泡而意外关闭模态框。

监听子元素事件

在极少数情况下,你希望 wire:model 也响应从子元素冒泡上来的事件,可以使用 .bubble 修饰符:

blade
<div wire:model.deep="value">
    <input type="text"> <!-- 这里的更改将更新 $value -->
</div>

谨慎使用 .bubble

大多数用例不需要监听子元素事件。只有在你确实需要从后代元素捕获事件时才使用 .bubble

深入了解

有关在 HTML 表单上下文中使用 wire:model 的更完整文档,请访问 Livewire 表单文档页面

另请参阅

  • 表单 — 使用 Livewire 构建表单的完整指南
  • 属性 — 了解数据绑定和属性管理
  • 验证 — 实时验证绑定的属性
  • 文件上传 — 使用 wire:model 绑定文件输入

参考

blade
wire:model="propertyName"

修饰符

修饰符描述
.live在用户输入时发送更新
.blur仅在 blur 事件时发送更新
.change仅在 change 事件时发送更新
.lazy.change 的别名
.debounce防抖更新 150ms(使用 .debounce.500ms 自定义时长)
.throttle节流更新到指定间隔(使用 .throttle.500ms
.live.debounce结合实时更新与自定义防抖时间
.preserve-scroll更新期间保持滚动位置(与 .live 一起使用)
.number在服务器上将文本值转换为 int
.boolean在服务器上将文本值转换为 bool
.fill页面加载时使用 HTML value 属性的初始值
.bubble同时监听从子元素冒泡上来的事件