在Vue3中實(shí)現(xiàn)動(dòng)態(tài)路由的示例代碼
選用技術(shù)棧vue3+typescripy+element-plus ui+router 4
編寫(xiě)通用動(dòng)態(tài)路由菜單
目標(biāo):根據(jù)路由配置信息,自動(dòng)生成菜單內(nèi)容。實(shí)現(xiàn)更通用、更自動(dòng)的菜單配置。
通用路由菜單組件實(shí)現(xiàn)步驟
1.提取通用路由文件
2.菜單組件讀取路由,動(dòng)態(tài)渲染菜單項(xiàng)
3.綁定跳轉(zhuǎn)事件
4.同步路由的更新到菜單項(xiàng)高亮
5.按需補(bǔ)充更多能力
(1)提取通用路由文件
把 router/index.ts 中的路由變量定義為單獨(dú)的文件 routes.ts,代碼如下:
export const routes: Array<RouteRecordRaw> = [ { path: '/shouye', name: '首頁(yè)', component: Shouye, }, { path: '/keichengxuexi', name: '課程學(xué)習(xí)', component: Courselearning, }, }
然后在 router/index.ts 中引入 routes.
(2)菜單組件讀取路由,動(dòng)態(tài)渲染菜單項(xiàng)
<script setup lang= ts > import { routes }from "../router/routes"; </script>
模板中根據(jù)路由數(shù)組渲染菜單:
<el-menu-item v-for="item in routes" :key="item.path"> {{ item.name }} </el-menu-item>
(3)綁定跳轉(zhuǎn)事件
import { useRoute, useRouter } from "vue-router"; const router = useRouter(); // 路由跳轉(zhuǎn)事件 const doMenuClick = (key: string) => { router.push({ path: key, }); };
模板修改:
<el-menu mode="horizontal" @menu-item-click="doMenuClick" > ... </el-menu>
(4)同步路由的更新到菜單項(xiàng)高亮
同步高亮原理:首先點(diǎn)擊菜單項(xiàng) => 觸發(fā)點(diǎn)擊事件并跳轉(zhuǎn)更新路由 => 更新路由后,同步去更新菜單欄的高亮狀態(tài)。
使用 Vue Router 的 afterEach 路由鉤子實(shí)現(xiàn):
const router = useRouter(); // Tab 欄選中菜單項(xiàng) const selectedKeys = ref(["/"]); // 路由跳轉(zhuǎn)后,更新選中的菜單項(xiàng) router.afterEach((to, from, failure) => { selectedKeys.value = [to.path]; });
模板引入變量:
<el-menu mode="horizontal" :default-active="selectedKeys[0]" @menu-item-click="doMenuClick" > </el-menu>
還可以給路由菜單組件增加更多能力。
(5)按需補(bǔ)充更多能力(可以參考網(wǎng)上的框架),比如根據(jù)配置控制菜單的顯隱
利用 routes 配置的 meta 屬性實(shí)現(xiàn)。routes.ts 中給路由配置新增一個(gè)標(biāo)志位 hideInMenu
,用于判斷路由是否顯隱:
{ path: "/hide", name: "隱藏頁(yè)面", component: HomeView, meta: { hideInMenu: true, }, },
然后根據(jù)該標(biāo)志位過(guò)濾路由數(shù)組,僅保留需要展示的元素。
不要用 v-for + v-if 去條件渲染元素,這樣會(huì)先循環(huán)所有的元素,導(dǎo)致性能的浪費(fèi)。
// 展示在菜單的路由數(shù)組 const visibleRoutes = routes.filter((item) => { if (item.meta?.hideInMenu) { return false; } return true; });
整體的代碼實(shí)現(xiàn)如下
菜單欄組件GlobalHeader.vue
<template> <div id="globalHeader"> <el-menu :default-active="selectedKeys[0]" class="el-menu-demo" mode="horizontal" @select="handleSelect" background-color="rgb(255, 165, 104)" text-color="white" active-text-color="rgb(0,0,51)"> <el-menu-item v-for="item in visibleRoutes" :key="item.path"> <el-sub-menu v-if="item.children" :index="item.path"> <template #title> {{ item.name }} </template> <el-menu-item v-for="child in item.children" :key="child.path" @click="doMenuClick(`${item.path}/${child.path}`)"> {{ child.name }} </el-menu-item> </el-sub-menu> <template v-else> <el-menu-item @click="doMenuClick(item.path)"> {{ item.name }} </el-menu-item> </template> </el-menu-item> </el-menu> </div> </template>
上述菜單由于加入了子菜單的原因,所以增加了一層if的判斷邏輯。這個(gè)路由下是否還有子路由。
<script setup lang="ts"> import { routes } from '../router/routes' import { useRouter } from 'vue-router' import { ref } from 'vue' const handleSelect = (key: string, keyPath: string[]) => { console.log(key, keyPath) } const router = useRouter(); //當(dāng)前選中的菜單項(xiàng) const selectedKeys = ref(["/"]); //路由跳轉(zhuǎn)時(shí),選中菜單項(xiàng)1 router.afterEach((to, from) => { selectedKeys.value = [to.path]; }) //展示在菜單中的路由 const visibleRoutes = routes.filter((item) => { if (item.meta?.hideInMenu) { console.log('隱藏的菜單:', item.name); return false; } return true; }) //點(diǎn)擊菜單跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面 const doMenuClick = (key: string) => { router.push({ path: key, }); } </script>
routes.ts 路由組件
import { RouteRecordRaw } from "vue-router"; import Shouye from "../views/Shouye.vue"; import Courselearning from "../views/Courselearning.vue"; //vue3引入路由的方式 export const routes: Array<RouteRecordRaw> = [ { path: '/shouye', name: '首頁(yè)', component: Shouye, }, { path: '/keichengxuexi', name: '課程學(xué)習(xí)', component: Courselearning, meta:{ hideInMenu: true, }, }, { path: '/ketangxiaolian', name: '課堂小練', children: [ { path: '/network-world', name: '神奇的網(wǎng)絡(luò)世界', component: Networld, }, { path: '/internet', name: '走進(jìn)互聯(lián)網(wǎng)', component: Internet, }, { path: '/information-collection', name: '網(wǎng)上收集信息', component: Collectinformation, }, { path: '/communication', name: '網(wǎng)上交流信息', component: Communication, }, { path: '/soho-network', name: '組件SOHO網(wǎng)絡(luò)', component: Sohonetwork, }, ] }, }
以上就是在Vue3中實(shí)現(xiàn)動(dòng)態(tài)路由的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue3動(dòng)態(tài)路由的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- vue3?Error:Unknown?variable?dynamic?import:?../views/的解決方案
- 前端單獨(dú)實(shí)現(xiàn)vue動(dòng)態(tài)路由的示例代碼
- Vue3動(dòng)態(tài)路由(響應(yīng)式帶參數(shù)的路由)變更頁(yè)面不刷新的問(wèn)題解決辦法
- vue3動(dòng)態(tài)路由+菜單欄的實(shí)現(xiàn)示例
- vite+vue3+tsx項(xiàng)目打包后動(dòng)態(tài)路由無(wú)法加載頁(yè)面的問(wèn)題及解決
- vue3.0基于views批量實(shí)現(xiàn)動(dòng)態(tài)路由的方法(示例代碼)
相關(guān)文章
一個(gè)因@click.stop引發(fā)的bug的解決
這篇文章主要介紹了一個(gè)因@click.stop引發(fā)的bug的解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01VUE寫(xiě)一個(gè)簡(jiǎn)單的表格實(shí)例
在本篇文章里小編給大家整理的是關(guān)于VUE中表格的寫(xiě)法實(shí)例以及相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們可以參考下。2019-08-08vue中$emit傳遞多個(gè)參(arguments和$event)
本文主要介紹了vue中$emit傳遞多個(gè)參(arguments和$event),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02vue修改props數(shù)據(jù)報(bào)錯(cuò)的問(wèn)題及解決
這篇文章主要介紹了vue修改props數(shù)據(jù)報(bào)錯(cuò)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08Vite配置優(yōu)雅的code?spliiting代碼分割詳解
這篇文章主要為大家介紹了Vite配置優(yōu)雅的code?spliiting代碼分割詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Vue前端實(shí)現(xiàn)截圖功能的簡(jiǎn)單步驟
本文介紹了如何使用html2canvas庫(kù)來(lái)實(shí)現(xiàn)HTML頁(yè)面或某個(gè)元素的截圖功能,文中通過(guò)代碼介紹的非常詳細(xì),需要注意的是此方法只能在瀏覽器環(huán)境中使用,需要的朋友可以參考下2024-10-10vue.js學(xué)習(xí)之vue-cli定制腳手架詳解
這篇文章主要給大家介紹了vue.js學(xué)習(xí)之vue-cli定制腳手架的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2017-07-07Vant?Weapp組件picker選擇器初始默認(rèn)選中問(wèn)題
這篇文章主要介紹了Vant?Weapp組件picker選擇器初始默認(rèn)選中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01