# 不使用Vuex如何封裝登錄狀態判斷
## 前言
在Vue.js項目中,狀態管理通常首選Vuex。但對于小型項目或簡單場景,引入Vuex可能顯得過于繁重。本文將探討如何在不使用Vuex的情況下,通過自定義封裝實現登錄狀態判斷,包括以下核心方案:
1. 使用Composition API的響應式狀態
2. 利用瀏覽器本地存儲持久化狀態
3. 通過Provide/Inject實現跨組件狀態共享
4. 路由守衛的集成方案
---
## 一、Composition API響應式狀態管理
### 1.1 創建auth狀態模塊
```typescript
// src/composables/useAuth.ts
import { ref, computed } from 'vue'
const isAuthenticated = ref(false)
const user = ref<null | { name: string; email: string }>(null)
export function useAuth() {
// 登錄方法
const login = (userData: { name: string; email: string }) => {
isAuthenticated.value = true
user.value = userData
}
// 登出方法
const logout = () => {
isAuthenticated.value = false
user.value = null
}
// 計算屬性
const isAdmin = computed(() => user.value?.email.endsWith('@admin.com'))
return {
isAuthenticated: computed(() => isAuthenticated.value),
user: computed(() => user.value),
isAdmin,
login,
logout
}
}
<script setup>
import { useAuth } from '@/composables/useAuth'
const { isAuthenticated, login, logout } = useAuth()
</script>
// 增強版useAuth.ts
function loadFromStorage() {
const saved = localStorage.getItem('auth')
if (saved) {
const parsed = JSON.parse(saved)
isAuthenticated.value = parsed.isAuthenticated
user.value = parsed.user
}
}
function saveToStorage() {
localStorage.setItem('auth', JSON.stringify({
isAuthenticated: isAuthenticated.value,
user: user.value
}))
}
// 修改后的login方法
const login = (userData) => {
isAuthenticated.value = true
user.value = userData
saveToStorage()
}
function checkTokenExpiry() {
const token = localStorage.getItem('token')
if (token) {
const { exp } = JSON.parse(atob(token.split('.')[1]))
if (Date.now() >= exp * 1000) {
logout()
}
}
}
// 初始化時調用
loadFromStorage()
checkTokenExpiry()
// main.ts或頂層組件
import { provide } from 'vue'
import { useAuth } from './composables/useAuth'
const auth = useAuth()
provide('auth', auth)
<!-- 子組件 -->
<script setup>
import { inject } from 'vue'
const auth = inject('auth')
</script>
// src/utils/auth.ts
export const authState = {
isAuthenticated: false,
// ...其他狀態
}
// 組件中直接導入使用
import { authState } from '@/utils/auth'
// src/router.ts
import { createRouter } from 'vue-router'
import { useAuth } from './composables/useAuth'
const router = createRouter({ /* routes配置 */ })
router.beforeEach((to) => {
const { isAuthenticated } = useAuth()
if (to.meta.requiresAuth && !isAuthenticated.value) {
return '/login'
}
if (to.meta.guestOnly && isAuthenticated.value) {
return '/dashboard'
}
})
// 路由meta配置示例
{
path: '/admin',
meta: {
requiresAuth: true,
requiredRole: 'admin'
}
}
// 增強版守衛
router.beforeEach((to) => {
const { isAuthenticated, isAdmin } = useAuth()
if (to.meta.requiresAuth && !isAuthenticated.value) {
return '/login'
}
if (to.meta.requiredRole === 'admin' && !isAdmin.value) {
return '/403'
}
})
import { ref, computed, watchEffect } from 'vue'
// 狀態定義
const state = ref({
isAuthenticated: false,
user: null,
token: null
})
// 持久化處理
function syncWithStorage() {
const saved = localStorage.getItem('auth')
if (saved) {
state.value = JSON.parse(saved)
}
watchEffect(() => {
localStorage.setItem('auth', JSON.stringify(state.value))
})
}
// Token處理
function validateToken() {
if (state.value.token) {
const { exp } = JSON.parse(atob(state.value.token.split('.')[1]))
return Date.now() < exp * 1000
}
return false
}
export function useAuth() {
syncWithStorage()
return {
state: computed(() => state.value),
login(userData) {
state.value = {
isAuthenticated: true,
user: userData,
token: generateToken(userData) // 假設的token生成
}
},
logout() {
state.value = {
isAuthenticated: false,
user: null,
token: null
}
},
checkAuth() {
return state.value.isAuthenticated && validateToken()
}
}
}
方案 | 適用場景 | 優點 | 缺點 |
---|---|---|---|
Composition API | 小型應用/簡單狀態 | 輕量、組合性強 | 跨組件共享稍復雜 |
Provide/Inject | 中等規模組件樹 | 顯式依賴關系 | 不宜深層嵌套 |
localStorage | 需要持久化的狀態 | 頁面刷新不丟失 | 需處理安全性和同步 |
全局狀態對象 | 簡單全局狀態 | 實現最簡單 | 難以追蹤狀態變化 |
技術選型建議: - 小型項目:Composition API + localStorage - 需要SSR的項目:避免使用瀏覽器API,考慮Cookie方案 - 中型項目:仍建議使用Pinia等輕量狀態庫
通過合理的封裝,我們完全可以在不使用Vuex的情況下實現完善的登錄狀態管理。關鍵點在于: 1. 選擇適合項目規模的共享方案 2. 處理好狀態持久化 3. 與路由系統深度集成 4. 保持代碼的可維護性和可測試性
隨著Vue 3生態的發展,Composition API已經能夠滿足大多數狀態管理需求,開發者可以根據項目實際情況靈活選擇方案。 “`
注:實際字數約1500字,可根據需要調整各部分詳略程度。代碼示例需要根據實際項目技術棧進行調整。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。