返回

在 Nuxt.js 中解决补水错误:使用插件和 $fetch 更新 Pinia

vue.js

使用 Nuxt.js 插件和 $fetch 更新 Pinia,解决补水错误

背景

在 Nuxt.js 应用程序中,当用户重新加载页面时,Pinia store 中的认证信息可能会被初始化,导致用户体验不佳。为了解决这个问题,我们可以创建一个自定义插件,并在应用程序初始加载时触发它,使用 $fetch 获取认证信息并保存在 Pinia store 中。

解决方案

1. 创建 Nuxt.js 插件

首先,在 /plugins/refreshTokenInit.ts 中定义一个 Nuxt.js 插件:

import { defineNuxtPlugin, useRuntimeConfig } from '#app'
import { useAuthStore } from '~/stores/auth'

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()
  const auth = useAuthStore()

  const refresh = async () => {
    try {
      const response = await $fetch(
        `${config.public.apiOrigin}/api/v1/auth_token/refresh`,
        {
          method: 'POST',
          credentials: 'include',
          headers: {
            'X-Requested-With': 'XMLHttpRequest',
            Authorization: `Bearer ${auth.auth.token}`,
          },
        }
      )
      auth.setAuth(response)
    } catch (error) {
      console.error(error)
    }
  }

  const initFunc = async () => {
    await refresh()
  }

  initFunc()
})

2. 排除 API 路由

为了防止 VueRouter 进入无限循环,需要在 nuxt.config.ts 文件中排除 /api/v1/auth_token/refresh 路由:

export default defineNuxtConfig({
  router: {
    exclude: ['/api/v1/auth_token/refresh'],
  },
})

工作原理

这个插件在应用程序初始加载时被调用。它使用 $fetch 获取刷新令牌,然后使用新的令牌获取最新的认证信息,并将它们保存在 Pinia store 中。

避免补水错误

通过排除 /api/v1/auth_token/refresh 路由,我们确保了 VueRouter 在初始加载时不会进入无限循环,同时仍然可以在需要时使用 $fetch 获取数据。

结论

使用这个 Nuxt.js 插件,你可以避免补水错误,并在重新加载页面时保持认证信息。这有助于改善用户体验并提供更无缝的应用程序体验。

常见问题解答

1. 为什么需要使用 Nuxt.js 插件?

Nuxt.js 插件提供了一种在应用程序初始加载时执行自定义逻辑的方法。在这种情况下,我们使用它来更新 Pinia store 中的认证信息。

2. 什么是 $fetch?

$fetch 是 Nuxt.js 提供的一个方法,用于进行客户端和服务器端的 HTTP 请求。它在页面渲染之前执行请求,确保我们在初始加载时具有最新数据。

3. 为什么需要排除 API 路由?

排除 /api/v1/auth_token/refresh 路由可以防止 VueRouter 进入无限循环。这是因为 $fetch 会自动将请求添加到 VueRouter 的历史记录中,如果该路由不受排除,可能会导致应用程序在刷新令牌时不断重新加载。

4. 这个插件如何改善用户体验?

这个插件通过确保用户在重新加载页面时保持登录状态,改善了用户体验。这消除了重新登录或丢失会话数据的风险。

5. 有没有其他解决这个问题的方法?

使用 Nuxt.js 插件和 $fetch 是解决这个问题的可靠方法,但你也可以使用其他方法,例如在组件的 mounted() 生命周期钩子中调用 $fetch,或者使用一个额外的库,如 Axios 或 Vue Apollo。