wire:model
Livewire 让你可以使用 wire:model 轻松将组件属性的值与表单输入绑定。
下面是一个简单示例,在「Create Post」组件中使用 wire:model 将 $title 和 $content 属性与表单输入绑定:
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
]);
// ...
}
}<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:click 或 wire:submit)发送网络请求,而不是在 wire:model 输入更新时。
这通过减少网络请求显著提升了 Livewire 的性能,并为用户提供更流畅的体验。
但有时你可能希望更频繁地更新服务器,例如用于实时验证。
实时更新
要在用户向输入字段键入时将属性更新发送到服务器,可以向 wire:model 追加 .live 修饰符:
<input type="text" wire:model.live="title">自定义防抖
默认情况下,使用 wire:model.live 时,Livewire 会为服务器更新添加 150 毫秒的防抖。这意味着若用户持续输入,Livewire 会等到用户停止输入 150 毫秒后再发送请求。
你可以通过在 .live 后追加 .debounce.Xms 来自定义此时间。下面是将防抖改为 250 毫秒的示例:
<input type="text" wire:model.live.debounce.250ms="title">在「blur」事件时更新
.blur 修饰符会延迟同步,直到用户点击离开输入框:
<input type="text" wire:model.blur="title">若要在 blur 时也发送网络请求,请添加 .live:
<input type="text" wire:model.blur.live="title">在「change」事件时更新
.change 修饰符在 change 事件时触发,对 select 元素很有用:
<select wire:model.change="state">...</select>
<!-- With network request -->
<select wire:model.change.live="state">...</select>在「enter」键时更新
.enter 修饰符在用户按下 Enter 键时同步:
<input type="text" wire:model.enter="search">
<!-- With network request -->
<input type="text" wire:model.enter.live="search">输入字段
Livewire 开箱即用地支持大多数原生输入元素。也就是说,你只需给浏览器中的任意输入元素加上 wire:model,就能轻松将属性绑定到它们。
以下是各种可用输入类型及其在 Livewire 中用法的完整列表。
文本输入
首先,文本输入是大多数表单的基础。下面是如何将名为「title」的属性绑定到文本输入:
<input type="text" wire:model="title">文本域输入
文本域元素同样简单。只需给 textarea 添加 wire:model,值就会被绑定:
<textarea type="text" wire:model="content"></textarea>若「content」值用字符串初始化,Livewire 会用该值填充 textarea——无需像下面这样做:
<!-- Warning: This snippet demonstrates what NOT to do... -->
<textarea type="text" wire:model="content">{{ $content }}</textarea>复选框
复选框可用于单个值,例如切换布尔属性;也可用于在一组相关值中切换单个值。我们将讨论这两种场景:
单个复选框
在注册表单末尾,你可能有一个允许用户选择接收邮件更新的复选框。你可以把该属性命名为 $receiveUpdates。使用 wire:model 即可轻松将该值绑定到复选框:
<input type="checkbox" wire:model="receiveUpdates">现在当 $receiveUpdates 值为 false 时,复选框未勾选;当值为 true 时,复选框会被勾选。
多个复选框
现在,假设除了让用户决定是否接收更新外,你的类中还有一个名为 $updateTypes 的数组属性,允许用户从多种更新类型中选择:
public $updateTypes = [];通过将多个复选框绑定到 $updateTypes 属性,用户可以选择多种更新类型,它们会被添加到 $updateTypes 数组属性中:
<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"]
单选按钮
要在单个属性的两个不同值之间切换,可以使用单选按钮:
<input type="radio" value="yes" wire:model="receiveUpdates">
<input type="radio" value="no" wire:model="receiveUpdates">下拉选择
Livewire 让使用 <select> 下拉菜单变得简单。给下拉菜单添加 wire:model 后,当前选中的值会绑定到所提供的属性名,反之亦然。
此外,无需手动给将要选中的 option 添加 selected——Livewire 会自动处理。
下面是一个填充了静态州列表的下拉选择示例:
<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 动态构建下拉选项:
<select wire:model="state">
@foreach (\App\Models\State::all() as $state)
<option value="{{ $state->id }}">{{ $state->label }}</option>
@endforeach
</select>若默认没有选中特定选项,你可能希望默认显示一个淡化的占位选项,例如「Select a state」:
<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 中的选项会正确变化:
<!-- 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 数组属性,取消选中时会移除:
<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 修饰符:
<div wire:model.deep="value">
<input type="text"> <!-- Changes here will update $value -->
</div>WARNING
谨慎使用 .deep
大多数用例不需要监听子元素事件。仅在你确实需要捕获后代元素事件时才使用 .deep。
访问嵌套属性
wire:model 支持用点号表示法绑定到嵌套属性、数组元素和表单对象字段:
<input type="text" wire:model="address.city">
<input type="text" wire:model="items.0.name">
<input type="text" wire:model="form.title">也支持括号表示法作为替代:
<input type="text" wire:model="address['city']">
<input type="text" wire:model="items[0].name">两种表示法等价——address['city'] 解析的路径与 address.city 相同。括号与点号表示法可在单个表达式中自由混用。
跳过渲染
.renderless 修饰符会向服务器发送实时模型更新,而不重新渲染组件:
<input type="text" wire:model.renderless.live="search">这对于应在服务器上持久化、但在消息完成后不应 morph 当前 DOM 的模型更新很有用。
因为 .renderless 只影响服务器消息,请将其与 .live 一起使用。
深入了解
要了解在 HTML 表单上下文中使用 wire:model 的更完整文档,请访问 Livewire 表单文档页面。
另见
- Forms — 使用 Livewire 构建表单的完整指南
- Properties — 了解数据绑定与属性管理
- Validation — 实时验证绑定属性
- File Uploads — 使用 wire:model 绑定文件输入
参考
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 | 更新期间保持滚动位置 |