路由
src/router/index.ts:
import { createRouter, createWebHashHistory } from 'vue-router'
import { useTokenStore } from '@/stores/token'
import Login from '@/views/Login.vue'
import Index from '@/views/Index.vue'
import TheWelcome from '@/components/TheWelcome.vue'
import Dashboard from '@/views/Dashboard.vue'
import User from '@/views/User.vue'
const router = createRouter({
history: createWebHashHistory(),
routes: [
{ path: '/login', name:'Login',component: Login },
{
path: '/', component: Index, redirect: { name: 'Dashboard' },
children: [
{ path: 'dashboard', name: 'Dashboard', component: Dashboard, meta: { requiresAuth: true } },
{ path: 'user', name: 'User', component: User ,meta: { requiresAuth: true }},
{ path: 'welcome', name: 'TheWelcome', component: TheWelcome }//瞎写的,展示冗余
]
},
// 404页面统一重定向至仪表盘组件
{
path: '/:pathMatch(.*)*',
redirect: '/dashboard'
}
],
})
router.beforeEach((to, from, next) => {
const tokenStore = useTokenStore();
tokenStore.initToken(); // 初始化 token
// 场景1:需认证但未登录 → 跳登录页
if (to.meta.requiresAuth && !tokenStore.hasToken) {
next({ name: 'Login' });
}
// 场景2:已登录时访问登录页 → 重定向至首页
else if (to.name === 'Login' && tokenStore.hasToken) {
next({ name: 'Dashboard' });
}
// 场景3:其他情况放行
else {
next();
}
});
export default router
- 404页面统一重定向至仪表盘组件。
- 添加一个全局导航守卫,实现路由控制&登录状态、权限的管理与校验。
- 子路由。还记得之前讲路由的文章里,我特别提到要注意一下子路由,这里就用到了(Vue3开发极简入门(10):路由&嵌套路由)。
- Index.vue的主布局使用嵌套子路由,就是将功能组件的页面展示放在MainLayout.vue的第二个RouterView内。如果不这么配置,其页面就会使用App.vue的第一个RouterView,这样就没有Title区和菜单区了(具体代码在下篇文章)。
Pinia
src/stores/token.ts:
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { type MenuItem } from '@/params'
import { getIconComponent } from '@/utils/icons'
export const useTokenStore = defineStore('token', () => {
const token = ref('')
const loginName = ref('')
// 定义菜单数据
const menuItems = ref<MenuItem[]>([])
const hasToken = computed(() => token.value.trim() !== '')
const currentUserName = computed(() => loginName.value)
const currentMenuItems = computed(() => menuItems.value)
const loginSuccess = (newToken: string, newLoginName: string, newMenuItems: MenuItem[]) => {
console.log('登录成功:', newToken, newLoginName);
token.value = newToken
loginName.value = newLoginName
menuItems.value = transformMenuIcons(newMenuItems)
//存储在LocalStorage中
localStorage.setItem("leoorgtoken", newToken)
localStorage.setItem("leoorgloginname", newLoginName)
localStorage.setItem("leoorgmenuitems", JSON.stringify(menuItems.value))
}
const logoutSuccess = () => {
token.value = ''
loginName.value = ''
menuItems.value = []
//清除LocalStorage
localStorage.removeItem("leoorgtoken")
localStorage.removeItem("leoorgloginname")
localStorage.removeItem("leoorgmenuitems")
}
/**
* 初始化Token
* 如果有现成的token、loginName和menuItems,则直接返回。
* 否则从LocalStorage中获取(如果存在的话)
* @returns void
*/
const initToken = () => {
if (token.value && loginName.value && menuItems.value.length > 0) {
return;
}
const tokenFromLocalStorage = localStorage.getItem('leoorgtoken');
const loginNameFromLocalStorage = localStorage.getItem('leoorgloginname');
const menuItemsFromLocalStorage = localStorage.getItem('leoorgmenuitems');
if (tokenFromLocalStorage && loginNameFromLocalStorage && menuItemsFromLocalStorage) {
token.value = tokenFromLocalStorage
loginName.value = loginNameFromLocalStorage
menuItems.value = JSON.parse(menuItemsFromLocalStorage)
}
}
// 递归转换菜单图标
const transformMenuIcons = (menus: MenuItem[]): MenuItem[] => {
return menus.map(menu => ({
...menu,
iconComponent: getIconComponent(menu.icon || ''),
children: menu.children ? transformMenuIcons(menu.children) : []
}))
}
return {
token,
currentUserName,
currentMenuItems,
loginName,
hasToken,
loginSuccess,
logoutSuccess,
initToken
}
})
跟之前基本一样(Vue3开发极简入门(20):聚焦式状态管理库Pinia),就是处理了一下菜单列表。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...



