Skip to content

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 类来更改现有元素的样式通常很有用。这种技术可用于更改背景颜色、降低不透明度、触发旋转动画等。

以下是使用 Tailwindopacity-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>