Vue嵌套路由的各種用法詳解
一、Vue 嵌套路由基礎(chǔ)
1. 定義嵌套路由
在 Vue Router 中,嵌套路由可以通過在路由配置中定義 children 屬性來實(shí)現(xiàn)。例如,以下是一個簡單的嵌套路由配置:
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/',
component: () => import('./views/Home.vue'),
},
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue'),
children: [
{
path: 'profile',
component: () => import('./views/Profile.vue'),
},
{
path: 'settings',
component: () => import('./views/Settings.vue'),
},
],
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
在這個例子中,/dashboard 是父路由,/dashboard/profile 和 /dashboard/settings 是子路由。
2. 使用嵌套路由
在父組件中,可以通過 來渲染子路由的組件:
<template>
<el-menu :default-active="$route.path" router>
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
二、Element Plus Menu 基礎(chǔ)用法
Element Plus 的 Menu 組件支持多種用法,包括水平菜單、垂直菜單、折疊菜單等。以下是一些基本用法:
1. 垂直菜單
<template>
<el-menu :default-active="$route.path" router>
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
在這個例子中,el-menu 的 router 屬性用于激活當(dāng)前路由對應(yīng)的菜單項(xiàng)。
2. 水平菜單
水平菜單可以通過設(shè)置 mode=“horizontal” 來實(shí)現(xiàn):
<template>
<el-menu mode="horizontal" :default-active="$route.path" router>
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
三、Vue 嵌套路由與 Element Plus Menu 的結(jié)合
1. 動態(tài)菜單
可以通過動態(tài)綁定數(shù)據(jù)來生成菜單項(xiàng)。例如,從后端獲取菜單數(shù)據(jù)并渲染:
<template>
<el-menu :default-active="$route.path" router>
<template v-for="item in menuData" :key="item.index">
<el-menu-item v-if="!item.children" :index="item.index">
{{ item.label }}
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>{{ item.label }}</template>
<el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
{{ child.label }}
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</template>
<script setup>
import { ref } from 'vue';
const menuData = ref([
{ index: '/home', label: '首頁' },
{ index: '/users', label: '用戶管理' },
{
index: '/dashboard',
label: '儀表盤',
children: [
{ index: '/dashboard/profile', label: '個人資料' },
{ index: '/dashboard/settings', label: '設(shè)置' },
],
},
]);
</script>
在這個例子中,menuData 是一個動態(tài)生成的菜單數(shù)據(jù)數(shù)組。
2. 路由模式
當(dāng)與 Vue Router 結(jié)合使用時,可以通過 router 屬性激活當(dāng)前路由對應(yīng)的菜單項(xiàng)。例如:
<template>
<el-menu :default-active="$route.path" router>
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
在這個例子中,el-menu 的 router 屬性會根據(jù)當(dāng)前路由路徑($route.path)自動激活對應(yīng)的菜單項(xiàng)。
3. 菜單事件處理
Element Plus 的 Menu 組件提供了多種事件,例如 select、open 和 close。可以通過這些事件來處理菜單的交互邏輯。例如:
<template>
<el-menu :default-active="$route.path" router @select="handleSelect">
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
<script setup>
import { ref } from 'vue';
const handleSelect = (index) => {
console.log(`Selected menu: ${index}`);
};
</script>
在這個例子中,handleSelect 方法會在菜單項(xiàng)被選中時觸發(fā)。
四、高級用法
1. 權(quán)限控制
在實(shí)際應(yīng)用中,通常需要根據(jù)用戶的權(quán)限動態(tài)顯示菜單項(xiàng)??梢酝ㄟ^在路由配置中添加權(quán)限屬性,并在菜單渲染時進(jìn)行過濾。例如:
const routes = [
{
path: '/home',
component: () => import('./views/Home.vue'),
meta: { requiresAuth: false },
},
{
path: '/users',
component: () => import('./views/Users.vue'),
meta: { requiresAuth: true },
},
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue'),
children: [
{
path: 'profile',
component: () => import('./views/Profile.vue'),
meta: { requiresAuth: true },
},
{
path: 'settings',
component: () => import('./views/Settings.vue'),
meta: { requiresAuth: true },
},
],
},
];
然后在菜單渲染時,根據(jù)用戶權(quán)限過濾菜單項(xiàng):
<template>
<el-menu :default-active="$route.path" router>
<template v-for="item in filteredMenuData" :key="item.index">
<el-menu-item v-if="!item.children" :index="item.index">
{{ item.label }}
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>{{ item.label }}</template>
<el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
{{ child.label }}
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</template>
<script setup>
import { ref, computed } from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const menuData = ref([
{ index: '/home', label: '首頁', meta: { requiresAuth: false } },
{ index: '/users', label: '用戶管理', meta: { requiresAuth: true } },
{
index: '/dashboard',
label: '儀表盤',
children: [
{ index: '/dashboard/profile', label: '個人資料', meta: { requiresAuth: true } },
{ index: '/dashboard/settings', label: '設(shè)置', meta: { requiresAuth: true } },
],
},
]);
const filteredMenuData = computed(() => {
return menuData.value.filter((item) => {
if (!item.children) {
return !item.meta.requiresAuth || store.state.isAuthenticated;
} else {
item.children = item.children.filter((child) => {
return !child.meta.requiresAuth || store.state.isAuthenticated;
});
return item.children.length > 0;
}
});
});
</script>
在這個例子中,filteredMenuData 是一個計算屬性,根據(jù)用戶的認(rèn)證狀態(tài)(store.state.isAuthenticated)動態(tài)過濾菜單項(xiàng)。
2. 菜單的動態(tài)加載
在某些情況下,菜單數(shù)據(jù)可能需要從后端動態(tài)加載??梢酝ㄟ^異步請求獲取菜單數(shù)據(jù),并在獲取完成后渲染菜單。例如:
<template>
<el-menu :default-active="$route.path" router v-if="menuData.length > 0">
<template v-for="item in menuData" :key="item.index">
<el-menu-item v-if="!item.children" :index="item.index">
{{ item.label }}
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>{{ item.label }}</template>
<el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
{{ child.label }}
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
const menuData = ref([]);
onMounted(async () => {
try {
const response = await axios.get('/api/menu');
menuData.value = response.data;
} catch (error) {
console.error('Failed to load menu data:', error);
}
});
</script>
在這個例子中,onMounted 生命周期鉤子用于在組件掛載時從后端加載菜單數(shù)據(jù)。
3. 菜單的國際化
在國際化應(yīng)用中,菜單項(xiàng)的標(biāo)題可能需要根據(jù)用戶的語言偏好動態(tài)顯示??梢酝ㄟ^ Vue I18n 來實(shí)現(xiàn)菜單的國際化。例如:
<template>
<el-menu :default-active="$route.path" router>
<template v-for="item in menuData" :key="item.index">
<el-menu-item v-if="!item.children" :index="item.index">
{{ $t(item.label) }}
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>{{ $t(item.label) }}</template>
<el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
{{ $t(child.label) }}
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</template>
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const menuData = ref([
{ index: '/home', label: 'menu.home' },
{ index: '/users', label: 'menu.users' },
{
index: '/dashboard',
label: 'menu.dashboard',
children: [
{ index: '/dashboard/profile', label: 'menu.profile' },
{ index: '/dashboard/settings', label: 'menu.settings' },
],
},
]);
</script>
<i18n>
{
"en": {
"menu": {
"home": "Home",
"users": "Users",
"dashboard": "Dashboard",
"profile": "Profile",
"settings": "Settings"
}
},
"zh": {
"menu": {
"home": "首頁",
"users": "用戶管理",
"dashboard": "儀表盤",
"profile": "個人資料",
"settings": "設(shè)置"
}
}
}
</i18n>
在這個例子中,$t 方法用于動態(tài)翻譯菜單項(xiàng)的標(biāo)題。
4. 菜單的折疊與展開
Element Plus 的 Menu 組件支持折疊和展開功能。可以通過設(shè)置 collapse 屬性來控制菜單的折疊狀態(tài)。例如:
<template>
<div>
<el-button @click="toggleCollapse">切換菜單</el-button>
<el-menu :default-active="$route.path" router :collapse="isCollapsed">
<el-menu-item index="/home">首頁</el-menu-item>
<el-menu-item index="/users">用戶管理</el-menu-item>
<el-sub-menu index="/dashboard">
<template #title>儀表盤</template>
<el-menu-item index="/dashboard/profile">個人資料</el-menu-item>
<el-menu-item index="/dashboard/settings">設(shè)置</el-menu-item>
</el-sub-menu>
</el-menu>
</div>
</template>
<script setup>
import { ref } from 'vue';
const isCollapsed = ref(false);
const toggleCollapse = () => {
isCollapsed.value = !isCollapsed.value;
};
</script>
在這個例子中,isCollapsed 是一個響應(yīng)式變量,用于控制菜單的折疊狀態(tài)。點(diǎn)擊按鈕時,toggleCollapse 方法會切換菜單的折疊狀態(tài)。
5. 菜單的自定義樣式
可以通過自定義 CSS 來調(diào)整菜單的樣式。例如:
.el-menu {
background-color: #f5f7fa;
border-right: none;
}
.el-menu-item {
color: #333;
}
.el-menu-item.is-active {
background-color: #409eff;
color: #fff;
}
.el-sub-menu__title {
color: #333;
}
.el-sub-menu__title:hover {
background-color: #e6f7ff;
}
在這個例子中,自定義了菜單的背景顏色、字體顏色和激活狀態(tài)的樣式。
五、完整示例
以下是一個完整的示例,結(jié)合了嵌套路由、動態(tài)菜單、權(quán)限控制、國際化和折疊功能:
- 路由配置
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/',
component: () => import('./views/Home.vue'),
meta: { requiresAuth: false },
},
{
path: '/users',
component: () => import('./views/Users.vue'),
meta: { requiresAuth: true },
},
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue'),
children: [
{
path: 'profile',
component: () => import('./views/Profile.vue'),
meta: { requiresAuth: true },
},
{
path: 'settings',
component: () => import('./views/Settings.vue'),
meta: { requiresAuth: true },
},
],
meta: { requiresAuth: true },
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
- 菜單組件
<template>
<div>
<el-button @click="toggleCollapse">切換菜單</el-button>
<el-menu :default-active="$route.path" router :collapse="isCollapsed">
<template v-for="item in filteredMenuData" :key="item.index">
<el-menu-item v-if="!item.children" :index="item.index">
{{ $t(item.label) }}
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>{{ $t(item.label) }}</template>
<el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
{{ $t(child.label) }}
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import { useStore } from 'vuex';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const store = useStore();
const menuData = ref([
{ index: '/home', label: 'menu.home', meta: { requiresAuth: false } },
{ index: '/users', label: 'menu.users', meta: { requiresAuth: true } },
{
index: '/dashboard',
label: 'menu.dashboard',
children: [
{ index: '/dashboard/profile', label: 'menu.profile', meta: { requiresAuth: true } },
{ index: '/dashboard/settings', label: 'menu.settings', meta: { requiresAuth: true } },
],
meta: { requiresAuth: true },
},
]);
const isCollapsed = ref(false);
const toggleCollapse = () => {
isCollapsed.value = !isCollapsed.value;
};
const filteredMenuData = computed(() => {
return menuData.value.filter((item) => {
if (!item.children) {
return !item.meta.requiresAuth || store.state.isAuthenticated;
} else {
item.children = item.children.filter((child) => {
return !child.meta.requiresAuth || store.state.isAuthenticated;
});
return item.children.length > 0;
}
});
});
</script>
<i18n>
{
"en": {
"menu": {
"home": "Home",
"users": "Users",
"dashboard": "Dashboard",
"profile": "Profile",
"settings": "Settings"
}
},
"zh": {
"menu": {
"home": "首頁",
"users": "用戶管理",
"dashboard": "儀表盤",
"profile": "個人資料",
"settings": "設(shè)置"
}
}
}
</i18n>
- 樣式
.el-menu {
background-color: #f5f7fa;
border-right: none;
}
.el-menu-item {
color: #333;
}
.el-menu-item.is-active {
background-color: #409eff;
color: #fff;
}
.el-sub-menu__title {
color: #333;
}
.el-sub-menu__title:hover {
background-color: #e6f7ff;
}
六、總結(jié)
通過結(jié)合 Vue 嵌套路由和 Element Plus 的 Menu 組件,可以實(shí)現(xiàn)功能豐富且靈活的導(dǎo)航菜單。本文介紹了從基礎(chǔ)用法到高級功能的多種場景,包括動態(tài)菜單、權(quán)限控制、國際化、折疊功能和自定義樣式。這些功能可以根據(jù)實(shí)際需求靈活組合,以滿足復(fù)雜應(yīng)用的需求。
以上就是Vue嵌套路由的各種用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue嵌套路由用法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
npm install -g @vue/cli安裝vue腳手架報錯問題(一般都能解決)
這篇文章主要介紹了npm install -g @vue/cli安裝vue腳手架報錯問題(一般都能解決),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
vue代理請求之Request?failed?with?status?code?404問題及解決
這篇文章主要介紹了vue代理請求之Request?failed?with?status?code?404問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Vue 兩個字段聯(lián)合校驗(yàn)之修改密碼功能的實(shí)現(xiàn)
本文以校驗(yàn)兩次密碼的一致性應(yīng)用,給出兩個可變屬性值的字段之間的聯(lián)合校驗(yàn)的典型解決方案,通過實(shí)例代碼給大家介紹Vue 兩個字段聯(lián)合校驗(yàn)之修改密碼功能的實(shí)現(xiàn),需要的朋友一起看看吧2021-07-07

