温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

不使用Vuex如何封装登录状态判断

发布时间:2022-02-18 09:03:38 来源:亿速云 阅读:170 作者:iii 栏目:编程语言
# 不使用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
  }
}

1.2 在组件中使用

<script setup>
import { useAuth } from '@/composables/useAuth'

const { isAuthenticated, login, logout } = useAuth()
</script>

二、状态持久化方案

2.1 结合localStorage

// 增强版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()
}

2.2 处理Token过期(JWT示例)

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()

三、跨组件状态共享

3.1 Provide/Inject模式

// 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>

3.2 全局状态模式

// src/utils/auth.ts
export const authState = {
  isAuthenticated: false,
  // ...其他状态
}

// 组件中直接导入使用
import { authState } from '@/utils/auth'

四、路由守卫集成

4.1 基础路由守卫实现

// 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'
  }
})

4.2 动态权限控制

// 路由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'
  }
})

五、完整实现示例

5.1 增强版useAuth.ts

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字,可根据需要调整各部分详略程度。代码示例需要根据实际项目技术栈进行调整。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI