您现在的位置是:首页 >技术交流 >vue3+ts 动态路由网站首页技术交流
vue3+ts 动态路由
一.关于动态路由与静态路由
动态路由和静态路由是网络中常用的两种路由配置方式,它们在工作原理、适用场景、优缺点等方面存在诸多不同,以下是详细的对比:
工作原理
-
静态路由:由网络管理员手动配置,指定到达特定网络或主机的路径。它不会自动调整,除非管理员手动修改配置。例如,管理员在路由器上明确指定,当数据包要去往某个特定网络时,应该通过某个特定的接口和下一跳地址。
-
动态路由:通过路由协议(如RIP、OSPF、BGP等)自动学习和更新路由信息。路由器之间会定期交换路由信息,根据网络拓扑的变化自动计算最优路径。例如,当网络中的链路状态发生变化时,动态路由协议会自动感知并重新计算路由,更新路由表。
配置复杂度
-
静态路由:配置相对简单,只需指定目标网络、子网掩码和下一跳地址或出接口即可。适合小型网络或对路由配置要求不复杂的场景。
-
动态路由:配置相对复杂,需要配置路由协议、相关参数(如认证、路由优先级等),并且需要对路由协议的原理和工作机制有较深入的了解。不过,一旦配置完成,它可以自动适应网络拓扑的变化。
路由表更新方式
-
静态路由:路由表不会自动更新,除非管理员手动修改。因此,当网络拓扑发生变化时,需要人工干预来更新路由表。
-
动态路由:路由表会根据路由协议的算法自动更新。例如,当链路中断或恢复时,动态路由协议会通过更新消息通知其他路由器,从而更新路由表。
适用场景
-
静态路由:适用于小型网络、网络拓扑结构简单且稳定的情况,例如小型企业网络或单个局域网。在这种场景下,手动配置路由相对容易且高效。
-
动态路由:适用于大型网络、网络拓扑结构复杂且经常变化的情况,例如互联网服务提供商(ISP)的骨干网络或大型企业网络。动态路由能够自动适应网络变化,减少人工维护工作量。
路由的设置各式各样,接下来我将分享最近学到的一种方法
二.结构管理
建立基础管理结构
将页面路由单独抽取出来写成文件进行管理,此时router.index.ts 只放一些共有的页面路由
dashboard.ts的内容如下
export default {
path: '/main/analysis/dashboard',
component: () => import('@/views/main/analysis/dashboard/dashboard.vue')
}
这时我们就会感觉非常麻烦,如果增加一个页面就要手动增加一个路由文件,麻烦又费时
这时候不得不提到一个插件了
下载插件 coderwhy
执行口令:
npm install coderwhy -g
创建文件
在项目文件夹根目录下执行口令
add3:表示vue3
department:表示所创建的文件名
-d:目标地址
回车之后,router文件夹下会自动创建相关文件夹,并已经完成路由书写,同时 我们创建的department.vue 文件也已经填写了基础的代码块
coderwhy add3page_setup departmenet -d src/views/system/department
我们应该在什么时候完成动态路由的加载?
在登录完成时,我们应当根据后端给我们返回的用户信息判断用户身份,并加载完成对应的路由
登录时,我们通常会在pinia 中 管理我们的用户信息。于是我决定自登录的pinia 拿到返回的用户信息后顺便添加相关路由
localCache.setCache:我封装的一个小组件,用来进行本地缓存
utils下新建map-menus .ts
import type { RouteRecordRaw } from 'vue-router'
function loadLocalRoutes() {
// 1.动态获取所有的路由对象, 放到数组中
// * 路由对象都在独立的文件中
// * 从文件中将所有路由对象先读取数组中
const localRoutes: RouteRecordRaw[] = []
// 1.1.读取router/main所有的ts文件
const files: Record<string, any> = import.meta.glob(
'../router/main/**/*.ts',
{
eager: true
}
)
// 1.2.将加载的对象放到localRoutes
for (const key in files) {
const module = files[key]
localRoutes.push(module.default)
}
return localRoutes
}
export let firstMenu: any = null
export function mapMenusToRoutes(userMenus: any[]) {
// 1.加载本地路由
const localRoutes = loadLocalRoutes()
// 2.根据菜单去匹配正确的路由
const routes: RouteRecordRaw[] = []
for (const menu of userMenus) {
for (const submenu of menu.children) {
const route = localRoutes.find((item) => item.path === submenu.url)
if (route) {
// 1.给route的顶层菜单增加重定向功能(但是只需要添加一次即可)
if (!routes.find((item) => item.path === menu.url)) {
routes.push({ path: menu.url, redirect: route.path })
}
// 2.将二级菜单对应的路径
routes.push(route)
}
// 记录第一个被匹配到的菜单
if (!firstMenu && route) firstMenu = submenu
}
}
return routes
}
在LoginStore中使用map-menus .ts,拿到返回值后遍历添加路由
import { defineStore } from 'pinia'
import {
accountLoginRequest,
getUserInfoById,
getUserMenusByRoleId
} from '@/service/login/login'
import { mapMenusToRoutes } from '@/utils/map-menus'
interface ILoginState {
token: string
userInfo: any
userMenus: any
}
const useLoginStore = defineStore('login', {
// 如何制定state的类型
state: (): ILoginState => ({
token: '',
userInfo: {},
userMenus: [],
}),
actions: {
async loginAccountAction(account: IAccount) {
// 1.账号登录, 获取token等信息
const loginResult = await accountLoginRequest(account)
const id = loginResult.data.id
this.token = loginResult.data.token
localCache.setCache(LOGIN_TOKEN, this.token)
// 2.获取登录用户的详细信息(role信息)
const userInfoResult = await getUserInfoById(id)
const userInfo = userInfoResult.data
this.userInfo = userInfo
// 3.根据角色请求用户的权限(菜单menus)
const userMenusResult = await getUserMenusByRoleId(this.userInfo.role.id)
const userMenus = userMenusResult.data
this.userMenus = userMenus
// 4.进行本地缓存
localCache.setCache('userInfo', userInfo)
localCache.setCache('userMenus', userMenus)
// 重要: 动态的添加路由
const routes = mapMenusToRoutes(userMenus)
routes.forEach((route) => router.addRoute('main', route))
// 5.页面跳转(main页面)
router.push('/main')
},
loadLocalCacheAction() {
// 1.用户进行刷新默认加载数据
const token = localCache.getCache(LOGIN_TOKEN)
const userInfo = localCache.getCache('userInfo')
const userMenus = localCache.getCache('userMenus')
if (token && userInfo && userMenus) {
this.token = token
this.userInfo = userInfo
this.userMenus = userMenus
// 3.动态添加路由
const routes = mapMenusToRoutes(userMenus)
routes.forEach((route) => router.addRoute('main', route))
}
}
}
})
export default useLoginStore
欢迎各位大佬指正