文章目錄
-
- 實現思路
- 調用后端接口獲取用戶權限
- 獲取頁面權限動態綁定到路由對象中
- 動態添加子頁面路由
?
實現思路
? ?emm,項目中使用動態路由實現根據后端返回的用戶詳情信息,動態將該用戶能夠訪問的頁面信息,動態生成并且綁定到路由對象中。但是后端返回的不包含像是頁面詳情頁,新增頁的權限路由,如果前端在路由對象中寫死的話,那每次進入頁面都得判斷是否將進入一個用戶沒有權限的頁面,但是路由中有存在的。所以就想著自己能不能根據后端現有返回的信息,前端自己生成類似詳情之類的動態路由。
調用后端接口獲取用戶頁面權限動態綁定到路由對象中
1.獲取用戶權限
async function getUserAuthority(ids:any) {let userAuthority = nulllet NewList = null//定義請求參數let params = {id:ids,permission_tree:1}//請求用戶的信息await get('/system/user/detail',params).then(res=>{if(res.status_code == 200){//userAuthority 存入查詢到該用戶信息 userAuthority = res.data//模擬該頁面是需要跳轉其他項目的地址let list =[{id: 119,children:[{id:1191,children:[],parent_id:119,name :'審單管理',slug:'web-system-exchangegoods-management',web_path : `/gongdan`,links:'https://blog.csdn.net/qq_45061461?type=lately'}],slug:'web-system-examineadocument',web_icon:'el-icon-coin',name :'審單管理',web_path: null,},{id: 117,children:[{children:[],id:1171,parent_id:117,slug:'web-system-exchangegoods-management',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='}],slug:'web-system-exchangegoods',web_icon:'el-icon-coin',name :'換貨留言列表',web_path: null,}]//將后端返回的用戶信息中的權限 和 自己定義的權限對象 合并一起NewList = userAuthority.permissions.concat(list);//將用戶的權限信息保存本地中sessionStorage.setItem('NavList',JSON.stringify(NewList))}})return NewList
}
?2.用戶登錄請求信息 方法我就不寫了
//調用定義的獲取權限方法
proxy.$PublicAPI.getUserAuthority(list.user_id).then((res) => {//res就是上個方法中返回的權限信息 然后調用將路由添加入路由對象的方法proxy.$PublicAPI.getRouteAddList();//獲取默認第一菜單的一個頁面的路徑進行跳轉proxy.$PublicAPI.getOnePagePath();});
3.調用動態追加路由對象的方法
async function getRouteAddList() {<!--定義存放路由信息對象-->let parentRoute = null;<!--判斷本地中是否存在權限信息-->if (sessionStorage.getItem('NavList')) {//list是 forEachRout方法返回的數據,將本地權限信息傳入,根據信息生成路由對象格式數據let list = forEachRout() <!--router.getRoutes().find(route => route.name === 'index') 查找路由對象中的路由信息中name名為index的路由對象,name = index的路由對象path指向 index.vue 有顯示頁面元素的路由視圖 <router-view /> -->parentRoute = router.getRoutes().find(route => route.name === 'index');<!--想自己生成的路由對象格式數據 追加到 /index中的chilrend中 -->list.forEach(item => {parentRoute.children.push(item);});<!--將定義好的路由數據格式對象添加到路由對象中-->router.addRoute(parentRoute);}
}
4.設計路由對象格式數據?forEachRout方法
function forEachRout (){//存放已經設計好的路由對象let list = [] //查找 ../../views/ 文件夾下所有的文件 views文件夾下是我存放的vue文件const module = import.meta.glob("../../views/**");<!-- 獲取本地的權限信息 -->let params = JSON.parse(sessionStorage.getItem('NavList'));<!-- 循環遍歷權限信息 -->params.forEach(item => {<!-- 判斷權限信息中web_path 是否是為string,為string類型就是用戶的頁面權限 這是后端返回的 -->if (typeof item.web_path === 'string') {<!-- 設計路由對象格式信息 -->let routerChildrenOne = {path: item.web_path,name: `${item.web_path}`,component: module[`../../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 是判斷是否需要跳轉外部鏈接的對象,就是第一個截圖中定義的兩個權限數據對象
-->
else {item.children.forEach(Citem => {let routerChildren = { <!-- 判斷對象中是否存在 links(跳轉鏈接)屬性,為存在的話,那么這個path將和其他同樣存在links屬性的對象公用一個頁面(所有需要跳轉外部的菜單都共同跳轉這一個頁面,所以這里使用了路由傳參來確定點擊他們不會只獲取到最近的一個需要外部跳轉的菜單,否則菜單中存在一個以上跳轉外部菜單,無論點擊哪一個都會跳轉同一個外部鏈接。并菜單包含此path全部高亮),就會存在下方截圖的錯誤-->path:Citem.links ? `${Citem.web_path}/:${Citem.id}` : Citem.web_path ,name: `${Citem.web_path}`,component: module[`../../views${Citem.web_path}/index.vue`],meta: {title: Citem.name,buts: [],requireAuth: true,keepAlive: true,externallink:Citem.links}};list.push(routerChildren);Citem.children.forEach(C_item_C => {let but = C_item_C.slug;routerChildren.meta.buts.push(but);});});}});//返回定義好的路由格式對象return list
}
所以,在配置路由格式對象中外部跳轉鏈接菜單通過動態路由傳參來避免出現這個問題.到此菜單的動態路由已經配置完成。
動態添加子頁面路由
但是我在想如果每個頁面中都存在類似新增和詳情的子頁面,但是后端返回的信息中未包含,自己怎么也解決動態生成。于是就回到了,后端目前返回給我的權限信息,還有獲取到veiws文件夾中的vue文件。
?1.后端返回的權限
2.veiws文件夾中已經存在的
3.實現,此方法就是 P4代碼片段的方法 只不過增加了幾個變量和調用了幾個方法:
?新增變量名:Eligiblelimitsofauthority? ,?aa
?新增調用方法的方法名:UpdataRouterList 、GetPossibleDetails?
?已經底部retrun之前的判斷對象是否存在component綁定的文件路由屬性
function forEachRout (){//存放已經設計好的路由對象let list = []<!-- 存放可能是新增頁面,詳情頁面 和編輯頁面的標識 -->let Eligiblelimitsofauthority = []<!-- 存放可能是新增頁面,詳情頁面 和編輯頁面的路由對象>let aa = [] //查找 ../../views/ 文件夾下所有的文件 views文件夾下是我存放的vue文件const module = import.meta.glob("../../views/**");<!-- 獲取本地的權限信息 -->let params = JSON.parse(sessionStorage.getItem('NavList'));<!-- 篩選出頁面中出現可能是新增、詳情或者編輯的信息 --> UpdataRouterList(params,Eligiblelimitsofauthority)<!-- 根據傳遞過來的可能是詳情或者編輯的信息,篩選出存在權限的數據,轉換成路由格式對象 -->aa = GetPossibleDetails(Eligiblelimitsofauthority,params,aa)<!-- 循環遍歷權限信息 -->params.forEach(item => {<!-- 判斷權限信息中web_path 是否是為string,為string類型就是用戶的頁面權限 這是后端返回的 -->if (typeof item.web_path === 'string') {<!-- 設計路由對象格式信息 -->let routerChildrenOne = {path: item.web_path,name: `${item.web_path}`,component: module[`../../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 是判斷是否需要跳轉外部鏈接的對象,就是第一個截圖中定義的兩個權限數據對象
-->
else {item.children.forEach(Citem => {let routerChildren = { <!-- 判斷對象中是否存在 links(跳轉鏈接)屬性,為存在的話,那么這個path將和其他同樣存在links屬性的對象公用一個頁面(所有需要跳轉外部的菜單都共同跳轉這一個頁面,所以這里使用了路由傳參來確定點擊他們不會只獲取到最近的一個需要外部跳轉的菜單,否則菜單中存在一個以上跳轉外部菜單,無論點擊哪一個都會跳轉同一個外部鏈接。并菜單包含此path全部高亮),就會存在下方截圖的錯誤-->path:Citem.links ? `${Citem.web_path}/:${Citem.id}` : Citem.web_path ,name: `${Citem.web_path}`,component: module[`../../views${Citem.web_path}/index.vue`],meta: {title: Citem.name,buts: [],requireAuth: true,keepAlive: true,externallink:Citem.links}};list.push(routerChildren);Citem.children.forEach(C_item_C => {let but = C_item_C.slug;routerChildren.meta.buts.push(but);});});}});<!-- 判斷轉換成路由格式數據中component有數據的對象,component不為空的時候就是標識項目中已經創建了這個新增,詳情 或編輯的頁面-->if(aa){aa.map(item=>{if(item.component != undefined)list.push(item)})}//返回定義好的路由格式對象return list
}
2.UpdataRouterList方法 篩選出頁面中出現可能是詳情或者編輯的信息
//篩選出頁面中出現可能是詳情或者編輯的信息
function UpdataRouterList(navlist:any,Eligiblelimitsofauthority:any) {<!-- 循環傳過來的本地權限數據對象中包含了 'create','edit' 和 'detail'的標識 -->navlist.map(item=>{if(item.slug.indexOf('create') != -1 || item.slug.indexOf('edit') != -1 || item.slug.indexOf('detail') != -1){<!-- 存入到可能包含新增,詳情,編輯的標識數組中 -->Eligiblelimitsofauthority.push(item.slug)}<!-- 判斷是否還有子數據,第一次循環的是下拉菜單 第二次循環的是下拉菜單中的點擊跳轉頁面的菜單,第三次循環點擊跳轉頁面的菜單中的 按鈕權限,主要是拿到按鈕權限菜單 這里是只有二級菜單,所以循環了三次,如果有多級也會一直循環下去,知道children中沒有數據-->>if(item.children){UpdataRouterList(item.children,Eligiblelimitsofauthority)}})
}
3.GetPossibleDetails 根據傳遞過來的信息,篩選出存在權限的數據, 轉換成路由信息,因為如果在本地中已經定義了全部的頁面新增,詳情,編輯等頁面,但是咱們還是需要根據后端返回的權限中,判斷咱們是否注冊該頁面的路由。
//根據傳遞過來的信息,篩選出存在權限的數據, 轉換成路由信息
function GetPossibleDetails(data:object,navlist:object,aa:any,) {<!-- 獲取項目中views文件夾下的所有vue文件 -->const module = import.meta.glob("../../views/**");<!-- 遍歷本地中的權限數據-->navlist.map(item=>{<!-- 傳遞過來的可能是 新增,詳情,編輯的權限標識 -->data.map(ditem =>{<!-- 判斷 item.web_path是否不為空,如果為空的話表明菜單是下拉菜單就不做操作 item.slug :這個菜單的標識 如:web-users 就是表示user(用戶)菜單 -->if(item.web_path != null && ditem == `${item.slug}-create` || ditem == `${item.slug}-edit` || ditem == `${item.slug}-detail`){<!-- 存放定義的路由數據格式對象 -->let list = {}<!-- 截取item.we_path 菜單路徑處理后的值,如:/user 我拿取user 后面作為/veiws/user,匹配views下的user文件夾 所以這里獲取的是該菜單存放的文件夾名稱 -->let path = ''if(item.web_path != null){<!-- 截取文件夾名稱 -->path = item.web_path.slice(item.web_path.lastIndexOf('/') + 1 , item.web_path.length)<!-- ditem是方法接收傳遞過來可能是新增,編輯,詳情的權限標識數組,判斷最后的-符號的后面是 'create':新增 ,'edit' :編輯 'detail':詳情 -->switch ( ditem.slice(ditem.lastIndexOf('-') + 1 , ditem.length)) {case 'create'://如果是新增list = {//定義新增頁面跳轉的路由路徑,如: path是截取到的文件名:user 那就path最后就是 :/usercreatepath: '/'+path + 'create',name: `${path}create`,<!-- 匹配本地vue文件中是否包含 module:views下所有的vue文件,path:文件夾名稱,item.web_path:vue文件名稱 -->component: module[`../../views/${path}${item.web_path}create.vue`],meta: {title: '新建' + item.name ,buts: [],requireAuth: true,keepAlive: true,externalLink: item.links,}}break;case 'edit':console.log('item-edit',item);list = {path: '/'+path + 'edit',name: `${path}edit`,component: module[`../../views/${path}${item.web_path}edit.vue`],meta: {title: item.name + '編輯' ,buts: [],requireAuth: true,keepAlive: true,externalLink: item.links,}}break;case 'detail':list = {path: '/'+path + 'detail',name: `${path}detail`,component: module[`../../views/${path}${item.web_path}detail.vue`],meta: {title: item.name + '詳情' ,buts: [],requireAuth: true,keepAlive: true,externalLink: item.links,}}break;}}aa.push(list)}})<!-- 判斷菜單中的chidren是否存在數據,如果沒有存在就表明是一級點擊跳轉菜單,parent_id :0 表示的是菜單 -->if(item.children && item.parent_id == 0){GetPossibleDetails( data,item.children,aa)}})return aa
}
小結
1.最后添加到路由對象中的數據,最后一個對象就是新增的動態子頁面路由
項目文件