Skip to content
全部文档

wire:model

Livewire 让你可以使用 wire:model 轻松将组件属性的值与表单输入绑定。

下面是一个简单示例,在「Create Post」组件中使用 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」按钮时,它们的值会与服务器端属性同步。

WARNING

「为什么我输入时组件没有实时更新?」

若你在浏览器中试过并困惑为何标题没有自动更新,那是因为 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 毫秒后再发送请求。

你可以通过在 .live 后追加 .debounce.Xms 来自定义此时间。下面是将防抖改为 250 毫秒的示例:

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

在「blur」事件时更新

.blur 修饰符会延迟同步,直到用户点击离开输入框:

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

若要在 blur 时也发送网络请求,请添加 .live

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

在「change」事件时更新

.change 修饰符在 change 事件时触发,对 select 元素很有用:

html
<select wire:model.change="state">...</select>

<!-- With network request -->
<select wire:model.change.live="state">...</select>

在「enter」键时更新

.enter 修饰符在用户按下 Enter 键时同步:

html
<input type="text" wire:model.enter="search">

<!-- With network request -->
<input type="text" wire:model.enter.live="search">

输入字段

Livewire 开箱即用地支持大多数原生输入元素。也就是说,你只需给浏览器中的任意输入元素加上 wire:model,就能轻松将属性绑定到它们。

以下是各种可用输入类型及其在 Livewire 中用法的完整列表。

文本输入

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

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

文本域输入

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

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

若「content」值用字符串初始化,Livewire 会用该值填充 textarea——无需像下面这样做:

blade
<!-- Warning: This snippet demonstrates what NOT to do... -->

<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 后,当前选中的值会绑定到所提供的属性名,反之亦然。

此外,无需手动给将要选中的 option 添加 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>

如你所见,select 菜单没有像文本输入那样的「placeholder」属性。相反,你必须在列表中添加一个 disabled 的 option 元素作为第一项。

联动下拉选择

有时你可能希望一个 select 菜单依赖另一个。例如,城市列表根据所选州而变化。

大部分情况下这会按预期工作,但有一个重要陷阱:你必须给会变化的 select 添加 wire:key,以便选项变化时 Livewire 能正确刷新其值。

下面是两个 select 的示例:一个选州,一个选城市。当州选择变化时,城市 select 中的选项会正确变化:

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

<!-- Cities dependent select menu... -->
<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>

同样,这里唯一非标准的是给第二个 select 添加的 wire:key。这确保州变化时,「selectedCity」值会被正确重置。

多选下拉

若使用「multiple」多选菜单,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 也响应从子元素冒泡上来的事件的场景中,可以使用 .deep 修饰符:

blade
<div wire:model.deep="value">
    <input type="text"> <!-- Changes here will update $value -->
</div>

WARNING

谨慎使用 .deep

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

访问嵌套属性

wire:model 支持用点号表示法绑定到嵌套属性、数组元素和表单对象字段:

blade
<input type="text" wire:model="address.city">

<input type="text" wire:model="items.0.name">

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

也支持括号表示法作为替代:

blade
<input type="text" wire:model="address['city']">

<input type="text" wire:model="items[0].name">

两种表示法等价——address['city'] 解析的路径与 address.city 相同。括号与点号表示法可在单个表达式中自由混用。

跳过渲染

.renderless 修饰符会向服务器发送实时模型更新,而不重新渲染组件:

blade
<input type="text" wire:model.renderless.live="search">

这对于应在服务器上持久化、但在消息完成后不应 morph 当前 DOM 的模型更新很有用。

因为 .renderless 只影响服务器消息,请将其与 .live 一起使用。

深入了解

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

另见

  • Forms使用 Livewire 构建表单的完整指南
  • Properties了解数据绑定与属性管理
  • Validation实时验证绑定属性
  • File Uploads使用 wire:model 绑定文件输入

参考

blade
wire:model="propertyName"
wire:model="property.nested"
wire:model="property['nested']"
wire:model="property[0]"

修饰符

修饰符说明
.live将更新发送到服务器
.blur仅在 blur 时更新
.change仅在 change 时更新
.enter仅在按下 Enter 键时更新
.lazy在 change 时更新并发送网络请求(兼容 v3)
.debounce.Xms防抖更新(与 .live 一起使用)
.throttle.Xms节流更新(与 .live 一起使用)
.number在服务器上将值转为 int
.boolean在服务器上将值转为 bool
.fill使用 HTML value 属性的初始值
.deep同时监听来自子元素的事件
.renderless实时模型更新后跳过重新渲染
.preserve-scroll更新期间保持滚动位置