AdSense

網頁

2026/1/19

Vue Nuxt 3 登入狀態管理

本篇介紹Vue Nuxt 3的前端登入狀態管理。


Vue Nuxt 3 登入驗證」中已經對SSR路由(瀏覽器直接輸入網址)進行驗證檢查,但前端只在login頁面登入時做過一次驗證,但後續的SPA路由(登入後在頁面內點選<NuxtLink>連結或執行程式中的navigateTo)都沒有再進行驗證,且前端目前無從得知登入狀態,所以下面會加入驗證狀態以便前端進行判別。


事前要求

參考「Vue Nuxt 3 登入驗證」。


新增登入驗證狀態

composables目錄下新增useAuth.ts,使用useState建立跨頁響應式共享狀態物件,名稱為"isLogin",初始值為false,此即為前端的[登入狀態],之後SPA路由時可用來判斷是否已通過驗證。

要注意useAuth只負責前端狀態的管理,且由於是存在Nuxt執行期間的記憶體中,重新整理瀏覽器時此狀態會被初始化,因此必須由後端SSR路由驗證成功後回填來同步。

composables/useAuth.ts

export const useAuth = () =>
  useState<boolean>('isLogin', () => false)


登入時設定狀態

修改pages/login.vue,引入useAuth,登入成功後把登入狀態isLogin設為true

pages/login.vue

<template>
  <h1>登入</h1>
  <!--...-->
</template>

<script setup lang="ts">
definePageMeta({
  layout: 'auth'
})

import { ref } from 'vue'
import type { LoginResponse } from '~/types/auth'

const isLogin = useAuth()
const username = ref('')
const password = ref('')

const login = async () => {
  try {
    const { success, token } = await $fetch<LoginResponse>('/api/auth/login', {
      method: 'POST',
      body: { username: username.value, password: password.value }
    })
    if (success && token) {
      isLogin.value = true // <--
      navigateTo('/home')
    }
  } catch (err) {
    alert('登入失敗,請稍後再試')
  }
}
</script>


修改驗證Middleware

修改middleware/auth.global.ts,SPA路由時if (import.meta.client)檢查[登入狀態]isLogin,若未登入(isLogin == false)則導回[登入頁面];在SSR驗證通過後同步前端[登入狀態],必免重新整理瀏覽器時useAuth被初始化,導致client hydration的時候在SPA路由登入驗證時被返回[登入頁面]。

middleware/auth.global.ts

export default defineNuxtRouteMiddleware((to) => {
  if (to.path === "/login") return; // 登入頁面不用驗證

  const isLogin = useAuth()

  // 檢查SSR路由登入驗證
  if (import.meta.server) {
    const token = useCookie("token").value;
    if (!token) {
      return navigateTo("/login");
    }
    isLogin.value = true; // 同步前端登入狀態
  }

  // 檢查SPA路由登入驗證
  if (import.meta.client) {
    if (!isLogin.value) {
      return navigateTo("/login");
    }
  }
});

github



接下來加入使用者角色和側邊選單的權限控管

沒有留言:

AdSense