进度指示器

由于 Inertia 请求是通过 XHR 发出的,因此在从一个页面导航到另一个页面时通常不会出现浏览器加载指示器。为了解决这个问题,Inertia 在您进行 Inertia 访问时会在页面顶部显示一个进度指示器。

当然,如果您愿意,可以禁用 Inertia 的默认加载指示器并提供您自己的自定义实现。我们将在下面讨论这两种方法。

默认

Inertia 的默认进度指示器是围绕 NProgress 库的轻量级包装器。您可以通过 progress 属性来自定义它 createInertiaApp() 功能。

createInertiaApp({
  progress: {
    // The delay after which the progress bar will appear, in milliseconds...
    delay: 250,

    // The color of the progress bar...
    color: '#29d',

    // Whether to include the default NProgress styles...
    includeCSS: true,

    // Whether the NProgress spinner will be shown...
    showSpinner: false,
  },
  // ...
})

您可以通过将 progress 属性设置为 false 来禁用 Inertia 的默认加载指示器。

createInertiaApp({
  progress: false,
  // ...
})

自定义

也可以使用 Inertia 事件 设置您自己的自定义页面加载指示器。让我们以 NProgress 库为例来探讨如何做到这一点。

首先,禁用 Inertia 的默认加载指示器。

createInertiaApp({
  progress: false,
  // ...
})

接下来,安装 NProgress 库。

npm install nprogress

安装后,您需要将 NProgress 样式 添加到您的项目中。您可以使用 CDN 托管的样式副本执行此操作。

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css" />

接下来,将 NProgress 和 Inertia router 导入到您的应用程序中。

import NProgress from 'nprogress'
import { router } from '@inertiajs/vue3'

接下来,让我们添加一个 start 事件监听器。我们将使用此监听器在新的 Inertia 访问开始时显示进度条。

router.on('start', () => NProgress.start())

然后,让我们添加一个 finish 事件监听器,以便在页面访问完成时隐藏进度条。

router.on('finish', () => NProgress.done())

就是这样!现在,当您从一个页面导航到另一个页面时,进度条将被添加到页面并从页面中删除。

处理取消的访问

虽然这种自定义进度实现对于正常完成的页面访问非常有效,但最好也处理取消的访问。首先,对于中断的访问(由于新的访问而被取消的访问),进度条应该简单地重置回起始位置。其次,对于手动取消的访问,进度条应该立即从页面中删除。

我们可以通过检查提供给 finish 事件的 event.detail.visit 对象来实现这一点。

router.on('finish', (event) => {
  if (event.detail.visit.completed) {
    NProgress.done()
  } else if (event.detail.visit.interrupted) {
    NProgress.set(0)
  } else if (event.detail.visit.cancelled) {
    NProgress.done()
    NProgress.remove()
  }
})

文件上传进度

让我们更进一步。当文件正在上传时,最好更新加载指示器以反映上传进度。这可以使用 progress 事件来完成。

router.on('progress', (event) => {
  if (event.detail.progress.percentage) {
    NProgress.set((event.detail.progress.percentage / 100) * 0.9)
  }
})

现在,文件上传时进度条不会“滴答”,而是会根据请求的进度更新其位置。我们在此处将进度限制为 90%,因为我们仍然需要等待服务器的响应。

加载指示器延迟

我们要实现的最后一件事是加载指示器延迟。通常最好延迟显示加载指示器,直到请求花费的时间超过 250-500 毫秒。这可以防止加载指示器在快速页面访问中不断出现,这在视觉上会分散注意力。

为了实现延迟行为,我们将使用 setTimeoutclearTimeout 函数。让我们首先定义一个变量来跟踪超时。

let timeout = null

接下来,让我们更新 start 事件监听器,以启动一个新的超时,该超时将在 250 毫秒后显示进度条。

router.on('start', () => {
  timeout = setTimeout(() => NProgress.start(), 250)
})

接下来,我们将更新 finish 事件监听器,以清除任何现有的超时,以防页面访问在超时之前完成。

router.on('finish', (event) => {
  clearTimeout(timeout)
  // ...
})

finish 事件监听器中,我们需要确定进度条是否实际上已经开始显示进度,否则我们将无意中导致它在超时完成之前显示。

router.on('finish', (event) => {
  clearTimeout(timeout)
  if (!NProgress.isStarted()) {
    return
  }
  // ...
})

最后,我们需要在 progress 事件监听器中进行相同的检查。

router.on('progress', event => {
  if (!NProgress.isStarted()) {
    return
  }
  // ...
}

就是这样,您现在拥有了一个漂亮的自定义页面加载指示器!

完整示例

为了方便起见,以下是我们自定义加载指示器的最终版本的完整源代码。

import NProgress from 'nprogress'
import { router } from '@inertiajs/vue3'

let timeout = null

router.on('start', () => {
  timeout = setTimeout(() => NProgress.start(), 250)
})

router.on('progress', (event) => {
  if (NProgress.isStarted() && event.detail.progress.percentage) {
    NProgress.set((event.detail.progress.percentage / 100) * 0.9)
  }
})

router.on('finish', (event) => {
  clearTimeout(timeout)
  if (!NProgress.isStarted()) {
    return
  } else if (event.detail.visit.completed) {
    NProgress.done()
  } else if (event.detail.visit.interrupted) {
    NProgress.set(0)
  } else if (event.detail.visit.cancelled) {
    NProgress.done()
    NProgress.remove()
  }
})