文章目录
-
- 需求整理
- 实现思路
- 实现过程
需求整理,实现思路
最近公司想将之前老的项目整理出来,因为这个老项目内容太杂什么页面都往里面塞,导致菜单特别多,公司就像将这个老的项目迁出来,这个旧的项目本来是后端PHP写的。没有前后分离,导致现在项目需要修改东西,都是后端自己做,导致处理成本增加。所以提出来将项目迁离出来,前后端分离。我们想的是新需求页面做在新项目然后再新的项目中显示旧项目页面。
现在我就想的是如果在新项目中显示旧的项目页面,但是在vue中路由跳转一般都是一个页面对应一个路由,旧项目页面太多上百个,如果旧页面还没迁离出来,新的项目已经有上百个文件来显示页面,太冗余了,就想着用一个页面现在没有迁离出来的就页面。
实现过程
1.新项目中获取后端返回的页面权限以及页面的路由等信息
2.后端返回的新页面信息,因为现在后端接口还没有出,我就用的其他测试项目数据来实现,后续只要跟后端沟通让他们传递你想要的数据格式即可。
这是后端返回的新项目页面信息,正常展示即可
3.设计后端返回旧页面数据
一、动态路由渲染
1.在我们拿到并处理数据后来实现动态绑定路由。定义路由格式然后绑定到你想要追加到路由中.
public.ts
async function getUserAuthority(ids:any) {
//获取用户菜单信息
let userAuthority = null
let NewList = null
let params = {
id:ids,
permission_tree:1
}
await get('/system/user/detail',params).then(res=>{
if(res.status_code == 200){
userAuthority = res.data
localStorage.setItem('userType',userAuthority.user_type)
//将权限信息保存在本地中
//自己编写的菜单信息,然后追加到后端返的菜单中
let list =[{
id: 116,
children:[{
id:1161,
children:[],
parent_id:116,
name :'审单管理',
web_path : `/gongdan`,
links:'https://blog.csdn.net/qq_45061461?type=lately'
}],
web_icon:'el-icon-coin',
name :'审单管理',
web_path: null,
},
{
id: 117,
children:[{
children:[],
id:1171,
parent_id:117,
name :'换货留言列表',
web_path : `/gongdan`,
links:'https://so.csdn.net/so/search?q=vue3%3Amian,ts%E4%B8%AD%E8%8E%B7%E5%8F%96import.meta.glob&t=&u=&urw='
}],
web_icon:'el-icon-coin',
name :'换货留言列表',
web_path: null,
}
]
NewList = userAuthority.permissions.concat(list);
sessionStorage.setItem('NavList',JSON.stringify(NewList))
}
})
return NewList
}
function forEachRout (){
//创建路由格式对象
const modules = import.meta.glob("../../views/**");//import.meta.glob来引入多个,单个的文件
let params = JSON.parse(sessionStorage.getItem('NavList'));
let list = [];
params.forEach(item => {
if (typeof item.web_path === 'string') {
let routerChildrenOne = {
path: item.web_path,
name: `${item.web_path}/:${item.icon}`,
component: modules[`../../views${item.web_path}/index.vue`],
meta: {
title: item.name,
buts: [],
requireAuth: true,
keepAlive: true,
externalLink: item.links,
}
};
list.push(routerChildrenOne);
let butOne = item.slug;
routerChildrenOne.meta.buts.push(butOne);
} else {
item.children.forEach(Citem => {
let routerChildren = {
//如上个函数中的 links就是跳转后端页面的路径, 如果有就改成动态参数路由
path:Citem.links ? `${Citem.web_path}/:${Citem.id}` : Citem.web_path ,
name: `${Citem.web_path}/:${Citem.id}`,
component: modules[`../../views${Citem.web_path}/index.vue`],
meta: {
title: Citem.name,
buts: [],
requireAuth: true,
keepAlive: true,
externallink:Citem.links
}
};
console.log('routerChildren',routerChildren);
list.push(routerChildren);
Citem.children.forEach(C_item_C => {
let but = C_item_C.slug;
routerChildren.meta.buts.push(but);
});
});
}
});
return list
}
async function getRouteAddList() {
let parentRoute = null;
if (sessionStorage.getItem('NavList')) {
let list = forEachRout()
//追加到 /index中的chilrend中
parentRoute = router.getRoutes().find(route => route.name === 'index');
list.forEach(item => {
parentRoute.children.push(item);
});
//将自己更新好的路由独享添加到路由中
router.addRoute(parentRoute);
}
return parentRoute
}
//修改外部路径共用一个页面导致路由匹错误的问题
function UpdataRouterObject(params:any){
let ro = forEachRout()
return ro.filter(item=> item.path == params.path)
}
2.将追加路由的函数完成返回结果
mian.ts中:
//此函数完成返回后再更注册路由,否则在项目中刷新页面就会出现空白页的情况
PublicAPI.getRouteAddList().then(res=>{
app.use(pinia)
app.use(ElementPlus)
app.use(router)
app.mount('#app')
})
3.路由:router.ts
const routes = [
{
path: "/",
name: 'login',
component: () => import('@/views/login/index.vue'),
},
{
path: "/index",
name: 'index',
component: () => import('@/views/index/index.vue'),
children:[
],
},
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
//路由前置守卫
router.beforeEach((to, from, next) => {
//判断进入的路径中是否包含了/gongdan ,就说明是要跳转外部链接的页面
if(to.fullPath.indexOf('/gongdan') !== -1){
//此方法是传递你将进入的页面信息,然后再获取到之前自己定义的路由数据中对比,重新将正确的路由信息返回回来 再重置掉跳转错误的页面
//如: path:/gongdan/:171 和 path:/gongdan/:161 他们跳转的路径不一样但是我需要那到的meta中的数据就一直会是 /gongdsn/:171中的meta所以要方法匹配重置
let params = PublicAPI.UpdataRouterObject(to)
to.name = params[0].name
to.meta = params[0].meta
next()
}else{
next();
}
_store.getNowRouterPath(to)
});
4.显示的页面
<script setup lang="ts">
import { onMounted } from "vue";
import useCurrentInstance from "@/hooks/useCurrentInstance";
const { proxy } = useCurrentInstance();
onMounted(()=>{})
</script>
<template>
<div>
//获取到路由传递过来的跳转路径
<iframe :src="proxy.$route.meta.externallink" style="width: 100%; height: 100vh;"></iframe>
</div>
</template>
<style scoped>
</style>
小提醒:登录页面后直接进入空白页但是页面上的路径是正确的跳转路径。
原因:项目启动的时候就会走mian.ts中的PublicAPI.getRouteAddList()方法但是该方法里面是获取本地中保存的menu菜单信息,所以本地没有的情况下动态添加的是空的,所以跳转页面会出现空白。
解决方法:
在登录的时候再调用一次该方法就行了
const data = await post("/login",ruleForm);
if(data.status_code == 200){
let list = data.data
localStorage.setItem("isAuthenticated", "true"); // 将用户认证状态保存在本地存储中
for (const key in list) {
if(key != 'expires_in'){
localStorage.setItem(key,list[key])
}
}
//获取权限
proxy.$PublicAPI.getUserAuthority(list.user_id).then(res=>{
//获取请求动态路由
proxy.$PublicAPI.getRouteAddList()
//获取默认第一菜单的一个页面的路径进行跳转
proxy.$PublicAPI.getOnePagePath()
})
}
} catch (error) {
console.error("发生错误:", error);
}
效果: