自己在使用C#搭建的界面是单页应用,所以需要使用vue中的vue-route做局部刷新,于是尝试element-plus结合route-view完成导航栏的搭建。在使用vue-route过程中自己一直没弄明白route-view是怎么将局部页面映射到对应的视图中,只是在menu中加router-view以及routes路由中有children时也需要加一层view就会正确的展示,后续弄懂原理再回来做补充。
配置路由
主要是添加自定义的菜单ICON,去掉App.vue中的首页导航
import type { RouteRecordRaw } from 'vue-router'
/**
* 路由配置
* @description 所有路由都在这里集中管理
*/
const routes: RouteRecordRaw[] = [
{
path: '/local',
name: 'home',
component: () =>
import(/* webpackChunkName: "home" */ '@cp/TransferStation.vue'),
meta: {
title: 'Home',
iconName: 'HomeFilled',
},
children: [
{
path: 'config',
name: '全局配置',
component: () =>
import(/* webpackChunkName: "bar" */ '@views/local/config.vue'),
meta: {
title: '全局配置',
iconName: 'Setting',
},
},
{
path: 'debug',
name: '调试',
component: () =>
import(/* webpackChunkName: "bar" */ '@views/local/debug.vue'),
meta: {
title: '调试',
iconName: 'Orange',
},
},
],
},
/**
* 子路由示例
*/
{
path: '/foo',
name: 'foo',
component: () =>
import(/* webpackChunkName: "foo" */ '@cp/TransferStation.vue'),
meta: {
title: 'Foo',
iconName: 'Shop',
},
redirect: {
name: 'bar',
},
children: [
{
path: 'bar',
name: 'bar',
component: () =>
import(/* webpackChunkName: "bar" */ '@views/foo/bar.vue'),
meta: {
title: 'Bar',
iconName: 'Ship',
},
},
],
},
]
export default routes
修改App.vue
在挂载时绑定C#调用js时的全局函数,直接挂载home.vue做导航
<template>
<HomeEntry></HomeEntry>
</template>
<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, onUpdated } from 'vue'
import router from '@/router'
import { getRoutePathByName } from '@/router/RouteUtil'
import { registerJiaJs, unRegisterJiaJs } from '@/plugins/local/jiaCb'
import { LoadGlobalConf } from '@/stores/local/config'
import HomeEntry from '@views/home.vue'
function onGetConfPage(page: string): void {
let path = getRoutePathByName(page)
console.log('load_first_page page=' + page + ';path=' + path)
router.push(path)
}
onMounted(() => {
registerJiaJs()
LoadGlobalConf(onGetConfPage)
})
onBeforeUnmount(() => {
unRegisterJiaJs()
})
</script>
首页导航的布局
首页主要是分头部,侧边栏以及右侧每个页面展示的区域,以下是相关的实现
Header.vue
<template>
<el-row align="middle">
<el-col :span="1" @click="onClikCollapse">
<el-icon v-if="!isCollapse" :size="30" color="hotpink"><Fold /></el-icon>
<el-icon v-else :size="30" color="hotpink"><Expand /></el-icon
></el-col>
<el-col :span="4"
><p><strong>云浮翼明</strong></p></el-col
><el-col :span="1" :offset="18"
><el-avatar :size="50" :src="avatar" /></el-col
></el-row>
</template>
<script setup>
import { toRefs } from 'vue'
import avatar from '@img/avatar.jpg'
const props = defineProps({ isCollapse: Boolean })
const emits = defineEmits(['onClikCollapse'])
const { isCollapse } = toRefs(props)
function onClikCollapse() {
emits('onClikCollapse')
}
</script>
<style scoped>
.el-row {
height: 70px;
flex-wrap: wrap;
flex-direction: row;
}
</style>
侧边栏在实现上需要注意el-menu-item中子路径的index拼接问题
<template>
<el-menu
:default-active="$route.path"
class="left-sidebar"
:collapse="isCollapse"
router
unique-opened
@open="handleOpen"
@close="handleClose"
>
<!-- 遍历菜单 -->
<template v-for="item in routes">
<!-- 含有子菜单 -->
<template v-if="item.children">
<!-- 第一层 含有子菜单菜单 -->
<el-sub-menu :index="item.path" :key="item.path">
<template #title>
<el-icon>
<component :is="item.meta.iconName" />
</el-icon>
<span>{{ item.meta.title }}</span>
</template>
<!-- 第二层 子菜单遍历 -->
<el-menu-item
v-for="subItem in item.children"
:key="subItem.path"
:index="item.path + '/' + subItem.path"
>
<el-icon>
<component :is="subItem.meta.iconName" />
</el-icon>
<template #title>
<span>{{ subItem.meta.title }}</span>
</template>
</el-menu-item>
</el-sub-menu>
</template>
<!-- 第一层 不含子菜单 -->
<template v-else>
<el-menu-item :index="item.path" :key="item.path">
<el-icon>
<component :is="item.meta.iconName" />
</el-icon>
<template #title>
<span>{{ item.meta.title }}</span>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
<script setup>
import { computed, ref, toRefs } from 'vue'
import { useRoute } from 'vue-router'
import routes from '@/router/routes'
const props = defineProps({ isCollapse: Boolean })
const { isCollapse } = toRefs(props)
const route = useRoute()
const handleOpen = (key, keyPath) => {
console.log(key, keyPath)
}
const handleClose = (key, keyPath) => {
console.log(key, keyPath)
}
</script>
<style scoped>
.left-sidebar:not(.el-menu--collapse) {
width: auto;
min-height: 400px;
}
</style>
最后整合到home.vue中
<template>
<div id="main">
<Header :isCollapse="isCollapse" @onClikCollapse="onClikCollapse"></Header>
<el-row>
<el-col :span="isCollapse ? 1 : 3">
<SideBar :isCollapse="isCollapse"></SideBar>
</el-col>
<el-col :span="isCollapse ? 23 : 21">
<router-view></router-view>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Header from '@cp/Header.vue'
import SideBar from '@cp/SideBar.vue'
const isCollapse = ref(true)
function onClikCollapse() {
isCollapse.value = !isCollapse.value
}
</script>
<style lang="less" scoped>
#main {
width: 100%;
height: 100%;
}
</style>
下面展示效果
展示导航