主题
wire:loading
加载指示器是制作良好用户界面的重要组成部分。当向服务器发出请求时,它们为用户提供视觉反馈,以便他们知道正在等待进程完成。
基本用法
Livewire 提供了一个简单但功能极其强大的语法来控制加载指示器:wire:loading。将 wire:loading 添加到任何元素将默认隐藏它(使用 CSS 中的 display: none),并在向服务器发送请求时显示它。
以下是 CreatePost 组件表单的基本示例,其中使用 wire:loading 来切换加载消息:
blade
<form wire:submit="save">
<!-- ... -->
<button type="submit">Save</button>
<div wire:loading> <!-- [tl! highlight:2] -->
Saving post...
</div>
</form>当用户按下"保存"时,"正在保存文章..."消息将在执行"save"操作时显示在按钮下方。当从服务器接收到响应并由 Livewire 处理时,消息将消失。
删除元素
或者,你可以附加 .remove 以获得相反的效果,默认显示元素并在向服务器发出请求期间隐藏它:
blade
<div wire:loading.remove>...</div>切换类
除了切换整个元素的可见性之外,在向服务器发出请求期间通过切换 CSS 类来更改现有元素的样式通常很有用。这种技术可用于更改背景颜色、降低不透明度、触发旋转动画等。
以下是使用 Tailwind 类 opacity-50 使"保存"按钮在提交表单时变淡的简单示例:
blade
<button wire:loading.class="opacity-50">Save</button>与切换元素一样,你可以通过将 .remove 附加到 wire:loading 指令来执行相反的类操作。在下面的示例中,当按下"保存"按钮时,按钮的 bg-blue-500 类将被删除:
blade
<button class="bg-blue-500" wire:loading.class.remove="bg-blue-500">
Save
</button>切换属性
默认情况下,提交表单时,Livewire 将在处理表单时自动禁用提交按钮并将 readonly 属性添加到每个输入元素。
但是,除了此默认行为之外,Livewire 还提供 .attr 修饰符,允许你切换元素上的其他属性或切换表单外部元素上的属性:
blade
<button
type="button"
wire:click="remove"
wire:loading.attr="disabled"
>
Remove
</button>由于上面的按钮不是提交按钮,因此按下时不会被 Livewire 的默认表单处理行为禁用。相反,我们手动添加了 wire:loading.attr="disabled" 来实现此行为。
针对特定操作
默认情况下,只要组件向服务器发出请求,就会触发 wire:loading。
但是,在具有多个可以触发服务器请求的元素的组件中,你应该将加载指示器的范围缩小到单个操作。
例如,考虑以下"保存文章"表单。除了提交表单的"保存"按钮之外,还可能有一个"删除"按钮,该按钮在组件上执行"remove"操作。
通过将 wire:target 添加到以下 wire:loading 元素,你可以指示 Livewire 仅在单击"删除"按钮时显示加载消息:
blade
<form wire:submit="save">
<button type="submit">Save</button>
<button type="button" wire:click="remove">Remove</button>
<div wire:loading wire:target="remove">
Removing post...
</div>
</form>当按下上述 Remove 按钮时,将向用户显示"正在删除文章..."消息。但是,当按下"保存"按钮时,不会显示该消息。
针对多个操作
你可能会发现自己处于这样一种情况:你希望 wire:loading 对页面上的某些(但不是全部)操作做出反应。在这些情况下,你可以将多个操作传递到 wire:target 中,用逗号分隔。例如:
blade
<form wire:submit="save">
<input type="text" wire:model.blur="title">
<!-- ... -->
<button type="submit">Save</button>
<button type="button" wire:click="remove">Remove</button>
<div wire:loading wire:target="save, remove"> <!-- [tl! highlight:2] -->
Updating post...
</div>
</form>加载指示器("正在更新文章...")现在仅在按下"删除"或"保存"按钮时显示,而不是在 $title 字段发送到服务器时显示。
针对操作参数
在同一操作从页面上的多个位置使用不同参数触发的情况下,你可以通过传入附加参数将 wire:target 进一步限定为特定操作。例如,考虑以下场景,其中页面上的每个文章都有一个"删除"按钮:
blade
<div>
@foreach ($posts as $post)
<div wire:key="{{ $post->id }}">
<h2>{{ $post->title }}</h2>
<button wire:click="remove({{ $post->id }})">Remove</button>
<div wire:loading wire:target="remove({{ $post->id }})"> <!-- [tl! highlight:2] -->
Removing post...
</div>
</div>
@endforeach
</div>如果不将 {{ $post->id }} 传递给 wire:target="remove",则当单击页面上的任何按钮时,都会显示"正在删除文章..."消息。
但是,由于我们向 wire:target 的每个实例传递唯一参数,Livewire 将仅在将匹配的参数传递给"remove"操作时显示加载消息。
针对属性更新
Livewire 还允许你通过将属性的名称传递给 wire:target 指令来针对特定的组件属性更新。
考虑以下示例,其中名为 username 的表单输入使用 wire:model.live 在用户键入时进行实时验证:
blade
<form wire:submit="save">
<input type="text" wire:model.live="username">
@error('username') <span>{{ $message }}</span> @enderror
<div wire:loading wire:target="username"> <!-- [tl! highlight:2] -->
Checking availability of username...
</div>
<!-- ... -->
</form>当用户在输入字段中键入时,服务器使用新用户名更新时,将显示"正在检查可用性..."消息。
排除特定加载目标
有时你可能希望为每个 Livewire 请求显示加载指示器,_除了_特定属性或操作。在这些情况下,你可以像这样使用 wire:target.except 修饰符:
blade
<div wire:loading wire:target.except="download">...</div>现在,上述加载指示器将为组件上的每个 Livewire 更新请求显示,除了"download"操作。
自定义 CSS display 属性
当 wire:loading 添加到元素时,Livewire 更新元素的 CSS display 属性以显示和隐藏元素。默认情况下,Livewire 使用 none 隐藏,使用 inline-block 显示。
如果你正在切换使用 inline-block 以外的显示值的元素,例如以下示例中的 flex,你可以将 .flex 附加到 wire:loading:
blade
<div class="flex" wire:loading.flex>...</div>以下是可用显示值的完整列表:
blade
<div wire:loading.inline-flex>...</div>
<div wire:loading.inline>...</div>
<div wire:loading.block>...</div>
<div wire:loading.table>...</div>
<div wire:loading.flex>...</div>
<div wire:loading.grid>...</div>延迟加载指示器
在快速连接上,更新通常发生得如此之快,以至于加载指示器在被删除之前只会在屏幕上短暂闪烁。在这些情况下,指示器更像是一种干扰而不是有用的功能。
因此,Livewire 提供了 .delay 修饰符来延迟指示器的显示。例如,如果你像这样向元素添加 wire:loading.delay:
blade
<div wire:loading.delay>...</div>只有请求超过 200 毫秒时,上述元素才会出现。如果请求在此之前完成,用户将永远不会看到指示器。
要自定义延迟加载指示器的时间量,你可以使用 Livewire 的有用间隔别名之一:
blade
<div wire:loading.delay.shortest>...</div> <!-- 50ms -->
<div wire:loading.delay.shorter>...</div> <!-- 100ms -->
<div wire:loading.delay.short>...</div> <!-- 150ms -->
<div wire:loading.delay>...</div> <!-- 200ms -->
<div wire:loading.delay.long>...</div> <!-- 300ms -->
<div wire:loading.delay.longer>...</div> <!-- 500ms -->
<div wire:loading.delay.longest>...</div> <!-- 1000ms -->使用 data-loading 样式化
Livewire 会自动向触发网络请求的任何元素添加 data-loading 属性。这允许你直接使用 CSS 或 Tailwind 样式化加载状态,而无需使用 wire:loading 指令。
使用 Tailwind 的 data 属性变体
你可以使用 Tailwind 的 data-[loading] 变体在元素加载时应用样式:
blade
<button
wire:click="save"
class="data-[loading]:opacity-50 data-[loading]:pointer-events-none"
>
Save Changes
</button>当单击按钮并且请求正在进行时,它将自动变为半透明且不可单击。
使用 CSS
如果你没有使用 Tailwind,可以使用标准 CSS 针对 data-loading 属性:
css
[data-loading] {
opacity: 0.5;
pointer-events: none;
}
button[data-loading] {
background-color: #ccc;
cursor: wait;
}样式化父元素和子元素
当子元素具有 data-loading 时,你可以使用 has-data-loading: 变体样式化父元素:
blade
<div class="has-data-[loading]:opacity-50">
<button wire:click="save">Save</button>
</div>或者从具有 data-loading 的父元素使用 in-data-loading: 变体样式化子元素:
blade
<button wire:click="save">
<span class="in-data-[loading]:hidden">Save</span>
<span class="hidden in-data-[loading]:block">Saving...</span>
</button>