主题
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:click 或 wire: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 表单文档页面。
另请参阅
参考
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 | 同时监听从子元素冒泡上来的事件 |