背景:我们在用element ui 写菜单导航组件的时候,很可能在开发的时候不知道以后会嵌套多少层,如果每添加一层就到菜单组件中嵌套多一层代码,不仅麻烦而且会导致代码冗余。
封装Sidebar组件
父组件Sidebar.vue
<template>
<div>
<el-menu :default-active="defaultActive" class="sidebar_menu" router unique-opened @open="handleOpen" @close="handleClose">
<!-- el-sub-menu和el-menu-item 可能会有多层嵌套,所以抽取出来封装成递归组件-->
<SidebarMenu :routes="routes"></SidebarMenu>
</el-menu>
</div>
</template>
<script setup>
import SidebarMenu from './components/SidebarMenu.vue';
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
const $route = useRoute()
const routes = $http.getRoutes() // 假设菜单权限从接口返回
// 默认选中菜单
const defaultActive = ref('')
watch(() => $route.fullPath, (newVal) => {
defaultActive.value = newVal
}, {
immediate: true
})
function handleOpen() {}
function handleClose() {}
</script>
子组件SidebarMenu.vue
<template>
<template v-for="(item,ind) in routes" :key="ind">
<el-sub-menu :index="item.fullPath" v-if="item.children && item.children.length">
<template #title>
<span>{{item.name}}</span>
</template>
<SidebarMenu :routes="item.children"></SidebarMenu>
</el-sub-menu>
<el-menu-item :index="item.fullPath" v-else>
<span>{{item.name}}</span>
</el-menu-item>
</template>
</template>
<script setup name="SidebarMenu"> // 递归组件,在script添加name属性,然后可以在模板中直接使用
const props = defineProps({
routes: {
type: Array,
default: []
},
})
</script>
到这里,菜单就可以根据路由来进行展示了,不管嵌套多少层都可以正常展示。
网友评论