Skip to content
全部文档

wire:loading

加载指示器是打造良好用户界面的重要部分。它们在向服务器发起请求时给用户视觉反馈,让用户知道自己正在等待某个过程完成。

TIP

可考虑改用 data-loading 选择器

虽然 wire:loading 很适合简单的显示/隐藏场景,但 Livewire v4 会在触发网络请求的元素上自动添加 data-loading 属性。这种方式通常更简单、更灵活——你可以直接用 Tailwind 设置加载样式,无需 wire:target 指令,而且在向其他组件派发事件时也能无缝工作。了解更多关于 data-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」时,在执行「save」操作期间,「Saving post...」消息会出现在按钮下方。当收到服务器响应并由 Livewire 处理完成后,该消息会消失。

移除元素

也可以追加 .remove 实现相反效果:默认显示元素,在向服务器请求期间隐藏:

blade
<div wire:loading.remove>...</div>

切换类名

除了切换整个元素的可见性外,在向服务器请求期间通过切换 CSS 类来改变现有元素的样式也很有用。该技术可用于更改背景色、降低不透明度、触发旋转动画等。

下面是一个简单示例,使用 Tailwindopacity-50 类,在表单提交期间让「Save」按钮变淡:

blade
<button wire:loading.class="opacity-50">Save</button>

与切换元素类似,你可以在 wire:loading 指令后追加 .remove 来执行相反的类操作。在下面的示例中,按下「Save」按钮时会移除按钮的 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

但在有多个可触发服务器请求的元素的组件中,你应将加载指示器限定到单个操作。

例如,考虑下面的「Save post」表单。除了提交表单的「Save」按钮外,可能还有一个执行组件「remove」操作的「Remove」按钮。

通过给下面的 wire:loading 元素添加 wire:target,你可以指示 Livewire 仅在点击「Remove」按钮时显示加载消息:

blade
<form wire:submit="save">
    <!-- ... -->

    <button type="submit">Save</button>

    <button type="button" wire:click="remove">Remove</button>

    <div wire:loading wire:target="remove">  <!-- [tl! highlight:2] -->
        Removing post...
    </div>
</form>

按下上面的「Remove」按钮时,会向用户显示「Removing post...」消息。但按下「Save」按钮时不会显示该消息。

定位多个操作

有时你希望 wire:loading 只响应页面上的部分操作而非全部。此时可以将多个操作用逗号分隔传入 wire:target。例如:

blade
<form wire:submit="save">
    <input type="text" wire:model.live.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>

加载指示器(「Updating post...」)现在仅在按下「Remove」或「Save」按钮时显示,而在将 $title 字段发送到服务器时不会显示。

定位操作参数

当同一操作在页面多处以不同参数触发时,你可以通过传入额外参数,将 wire:target 进一步限定到特定操作。例如,页面上每篇文章都有一个「Remove」按钮:

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",点击页面上任意按钮都会显示「Removing post...」消息。

但因为我们为每个 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>

当用户在输入框中键入、服务器用新用户名更新时,会显示「Checking availability...」消息。

排除特定加载目标

有时你可能希望为除特定属性或操作外的每一个 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),可以向 wire:loading 追加 .flex

blade
<div class="flex" wire:loading.flex>...</div>

以下是可用 display 值的完整列表:

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>

另见

  • Loading States使用 data-loading 属性的现代方法
  • Actions在操作处理期间显示反馈
  • Forms显示表单提交进度

参考

blade
wire:loading
wire:target="action"
wire:target="property"
wire:target.except="action"

修饰符

修饰符说明
.remove默认显示元素,加载期间隐藏
.class="class-name"加载期间添加 CSS 类
.class.remove="class-name"加载期间移除 CSS 类
.attr="attribute"加载期间添加 HTML 属性
.delay延迟 200ms 显示指示器
.delay.shortest延迟 50ms
.delay.shorter延迟 100ms
.delay.short延迟 150ms
.delay.long延迟 300ms
.delay.longer延迟 500ms
.delay.longest延迟 1000ms
.inline-flex使用 inline-flex display 值
.inline使用 inline display 值
.block使用 block display 值
.table使用 table display 值
.flex使用 flex display 值
.grid使用 grid display 值