您提供的代码是一个Vue 3的权限守卫组件,它通过计算属性isAuthenticated
判断用户是否已登录,并根据状态渲染不同内容:
这个组件本质是一个高阶组件(HOC),用于保护需要认证的内容区域。
<template>
<div class="app">
<AuthGuard>
<!-- 这里的内容只有登录后才能看到 -->
<Dashboard />
</AuthGuard>
</div>
</template>
<script setup>
import AuthGuard from '@/components/AuthGuard.vue';
import Dashboard from '@/views/Dashboard.vue';
</script>
您可以通过作用域插槽自定义未登录状态下的显示内容:
<AuthGuard>
<template #unauthenticated>
<div class="custom-login-prompt">
<p class="text-red-500">请先登录以访问此内容</p>
<CustomLoginButton />
</div>
</template>
<AuthenticatedContent />
</AuthGuard>
您可以通过添加props支持基于角色的权限控制:
<!-- components/AuthGuard.vue -->
<template>
<div v-if="hasAccess">
<slot />
</div>
<div v-else>
<p v-if="!isAuthenticated">请先登录</p>
<p v-else>您没有权限访问此内容</p>
<button @click="redirectToLogin">登录</button>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useAuthStore } from '@/stores/auth';
import { useRouter } from 'vue-router';
const props = defineProps({
roles: {
type: Array,
default: () => [], // 允许的角色列表
},
redirect: {
type: String,
default: 'Login', // 未登录时的重定向路由名
},
});
const authStore = useAuthStore();
const router = useRouter();
const isAuthenticated = computed(() => authStore.isAuthenticated);
// 计算是否有权限访问
const hasAccess = computed(() => {
if (!isAuthenticated.value) return false;
if (props.roles.length === 0) return true; // 没有角色限制
// 检查用户角色是否在允许的列表中
return props.roles.includes(authStore.user?.role);
});
const redirectToLogin = () => {
router.push({ name: props.redirect });
};
</script>
为权限切换添加平滑过渡:
<template>
<transition name="fade">
<div v-if="hasAccess">
<slot />
</div>
<div v-else>
<p v-if="!isAuthenticated">请先登录</p>
<p v-else>您没有权限访问此内容</p>
<button @click="redirectToLogin">登录</button>
</div>
</transition>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
<AuthGuard roles="['admin', 'editor']">
<!-- 只有管理员和编辑可以看到 -->
<AdminPanel />
</AuthGuard>
<AuthGuard roles="['user']">
<!-- 普通用户可以看到 -->
<UserDashboard />
</AuthGuard>
虽然该组件主要用于模板,但也可以在路由级别结合使用:
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';
import AdminView from '../views/AdminView.vue';
import { useAuthStore } from '@/stores/auth';
const routes = [
{
path: '/',
name: 'Home',
component: HomeView,
},
{
path: '/admin',
name: 'Admin',
component: () => import('../views/AdminView.vue'),
meta: { requiresAuth: true, roles: ['admin'] },
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
// 全局路由守卫
router.beforeEach((to, from, next) => {
const authStore = useAuthStore();
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
next({ name: 'Login' });
} else if (to.meta.roles && !to.meta.roles.includes(authStore.user?.role)) {
// 使用AuthGuard组件处理无权限情况
next({ name: 'Forbidden' });
} else {
next();
}
});
export default router;
确保您的Auth Store提供必要的状态和方法:
// stores/auth.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useAuthStore = defineStore('auth', () => {
const user = ref(null);
const token = ref(localStorage.getItem('token') || null);
const isAuthenticated = computed(() => !!token.value);
const login = async (credentials) => {
// 登录逻辑...
token.value = 'your_token_here';
localStorage.setItem('token', token.value);
};
const logout = () => {
token.value = null;
user.value = null;
localStorage.removeItem('token');
};
return {
user,
token,
isAuthenticated,
login,
logout,
};
});
通过这个权限守卫组件,您可以:
这个组件设计遵循了Vue 3的Composition API风格,具有良好的可扩展性和可维护性。
Vue, 权限守卫,组件使用方法,路由守卫,导航守卫,全局守卫,路由权限控制,权限管理,组件封装技巧,Vue 组件开发,前端权限控制,前端开发,Vue 路由配置,扩展封装,Vue 实战
资源地址:
https://pan.quark.cn/s/dc62840f6d67
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。