目的
项目分为全局路由如登录页面,404页面之类的和由侧边栏menu控制跳转的子路由页面主要是业务页面。页面子页面放入views文件夹下,将自动读入注册成route,配置文件主要用于生成树形menu侧边栏。建议配合项目结构进行阅读效果更佳
效果
项目结构
子页面配置文件
将根据以下配置文件生成树形menu导航栏
exportdefault[{
url:"/page1",
meta:{ title:'页面1', requiresAuth:false},
children:[{
url:"/page2",
meta:{
requiresAuth:false,
title:"页面2"},
children:[{
url:"/page3",
meta:{
requiresAuth:false,
title:"页面3"}},],},],},{
url:"/page4",
meta:{ title:'页面4', requiresAuth:false}}]
全局页面配置文件
exportdefault[{
url:"/login",
meta:{ title:'登录', requiresAuth:false}},]
侧边栏模板组件
sideBar组件
<template><divclass="side-bar-wrapper" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"><el-asideclass="index-aside":width="isSideBarExpand?'65px':'150px'"><divclass="title_banner"></div><el-menuclass="aside-menu":collapse="isSideBarExpand"
ref="sideBar":default-active="onRoutes"
text-color="#a5a5a5"
active-text-color="#00c1de"
background-color="#414549"
unique-opened
menu-trigger="click":collapse-transition="collapseTransition"><template v-for="(item) in menuList"><el-menu-item
v-if="!item.list":index="item.route":key="item.route"
@click="barHref(item.route)"><icon-svg:icon-class="item.icon":class="{'avtive_bar_icon':item.route== onRoutes,'bar_icon':item.route!= onRoutes}"/><span slot="title"class="bar_title">{{item.title}}</span></el-menu-item><TreeMenu:key="item.route+'s'" v-if="item.list":item="item"></TreeMenu></template></el-menu></el-aside></div></template><script>import pagefrom"@/config/router/pages.js";import TreeMenufrom"./menu";exportdefault{
name:"sideBar",created(){this.getCachePage();},
components:{ TreeMenu},data(){return{
isCollapse:false,
isSideBarExpand:true,
collapseTransition:false,
menuList:[]};},
methods:{asyncgetCachePage(){this.menuList=this.creatMenu(page);},/*
保存被打开的侧边栏的状态
*/onMouseEnter(){this.isSideBarExpand=false;let menuRoute="";this.menuList.forEach(x=>{if(x.list&& x.list.length>0){if(
x.list.find(y=>{return y.route===this.onRoutes;})){
menuRoute= x.route;}}});if(menuRoute)this.$refs.sideBar.open(menuRoute);},onMouseLeave(){this.isSideBarExpand=true;},showSideBar(){this.isCollapse=!this.isCollapse;},creatMenu(list){var menuList=[];
list.forEach(s=>{let menu={
title: s.meta.title,
icon: s.url.replace("/",""),
index: s.url.replace("/",""),
route: s.url,
list:
s.children&& s.children.length>0?this.creatMenu(s.children): undefined};
menuList.push(menu);});return menuList;},barHref(s){if(s==this.onRoutes)returnthis.$router.push({ path: s});}},
computed:{onRoutes(){returnthis.$route.path;}}};</script><style lang="scss">.side-bar-wrapper{
height:100%;
z-index:20;}.title_banner{
width:100%;
height:50px;}.side-bar-wrapper.index-aside{
overflow: hidden;
position: absolute;
left:0;
top:0;
bottom:0;
z-index:20;// padding-top: 20px;
background: #414549;-webkit-transition: width0.3s;
transition: width0.3s;.el-menu{
border-right: none;.el-menu-item{// padding-left: 20px !important;}}}.side-bar-wrapper.index-aside.aside-menu{
height:100%;}.side-bar-wrapper.index-aside.aside-menu.nav-icon{
width:20px;
height:20px;}.side-bar-wrapper.index-aside.el-menu{
overflow: hidden;}.bar_icon{
color: #fff;}.avtive_bar_icon{
color: #00c1de;}.bar_title{
margin-left:5px;}</style>
menu组件
主要用于树形嵌套结构
<template><el-submenu
v-if="item.title&&item.list":index="item.route":key="item.route":show-timeout="0":hide-timeout="0"><template slot="title"><div><icon-svg:icon-class="item.icon":class="{'avtive_bar_icon':inParentPage(item.list,onRoutes),'bar_icon':!inParentPage(item.list,onRoutes)}"/><span slot="title" style="margin-left:3px">{{item.title}}</span></div></template><template v-for="(it) in item.list"><el-menu-item v-if="!it.list":index="it.route":key="it.route" @click="barHref(it.route)"><icon-svg:icon-class="it.icon":class="{'avtive_bar_icon':it.route== onRoutes,'bar_icon':it.route!= onRoutes}"/><span slot="title"class="bar_title">{{it.title}}</span></el-menu-item><TreeMenu:key="it.route+'s'" v-if="it.list":item="it"></TreeMenu></template></el-submenu></template><script>exportdefault{
props:["item"],
name:"TreeMenu",
methods:{barHref(s){if(s==this.onRoutes)returnthis.$router.push({ path: s});},inParentPage(list,page){let flag=falsefunctionloop(pages,p){for(let i=0;i<pages.length;i++){if(pages[i].route==p){
flag=true;break}if(pages[i].list){loop(pages[i].list,page)}}}loop(list,page)return flag},},
computed:{onRoutes(){returnthis.$route.path;}}};</script><style scoped lang='scss'>.bar_icon{
color: #fff;}.avtive_bar_icon{
color: #00c1de;}.bar_title{
margin-left:5px;}</style>
结合Element 布局组件,生成主页面
<template><el-containerclass="content"><side-bar></side-bar><el-containerclass="main-container"><el-header style="height:50px"><common-header ref="commomHeader"></common-header></el-header><el-main><router-view:key="key"></router-view></el-main></el-container></el-container></template><script>import sideBarfrom"./sideBar.vue";import commonHeaderfrom"./commonHeader.vue";exportdefault{
components:{ sideBar, commonHeader},
computed:{key(){returnthis.$route.name!== undefined?this.$route.name++newDate():this.$route++newDate();}}};</script><style lang='scss'>.el-container{
position: relative;}.el-header{
padding:0px;}.main-container{
margin-left:65px;}</style>
vue router 配置,读取页面配置文件自动注册路由
import pagefrom'./pages.js'import globalPagefrom'./globalPages.js'import Routerfrom'vue-router'const vueRouter=newRouter({
mode:'history',
routes:[...getRouteList(globalPage)]})
vueRouter.addRoutes([{
path:'/',
name:'index',
component: resolve=>require(["@/globalViews/main/main.vue"], resolve),
children:[...getRouteList([...page])],// redirect: page[0].url // 默认index重定向到home页面}])// 全局钩子,单独页面钩子在配置项单独设置
vueRouter.beforeEach((to,from, next)=>{if(to.meta.requiresAuth&&!localStorage.getItem("Token")){
console.warn('没有权限,跳转到登录')next('/login')}else{next()}})// 根据配置生成route对象集合functiongetRouteList(routes){let res=[]lethander=function(list){
list.forEach((s)=>{if(s.children){hander(s.children)}if(s.url){let route={
path: s.url,
component: resolve=>require(["@/views"+ s.url+ s.url+".vue"], resolve),
name: s.url.replace('/',''),
meta: s.meta}
res.push(route)}})}hander(routes)// console.log(res)return res}exportdefault vueRouter;
将Router配置注入Vue构造
import Vuefrom'vue'import Appfrom'./App.vue'import VueRouterfrom'vue-router';import routerfrom'@/config/router/index'
Vue.config.productionTip=false
Vue.use(VueRouter)newVue({
router,
render: h=>h(App),}).$mount('#app')
总结
还是react清晰好使
https://blog.csdn.net/weixin_39168678/article/details/107315893