ElementUI+命名視圖實(shí)現(xiàn)復(fù)雜頂部和左側(cè)導(dǎo)航欄
在了解了命名視圖的用途后,發(fā)現(xiàn)用命名視圖來(lái)實(shí)現(xiàn)復(fù)雜導(dǎo)航更加省力。更多知識(shí)請(qǐng)參考這里
這里只說(shuō)明重要配置內(nèi)容,其他內(nèi)容配置請(qǐng)參考上一篇初始版本:
ElementUI 復(fù)雜頂部和左側(cè)導(dǎo)航欄實(shí)現(xiàn)
或參考文末提到的github上的項(xiàng)目代碼。
項(xiàng)目目錄如下:

1、router配置(router/index.js)如下:
import Vue from 'vue'
import Router from 'vue-router'
import TopNav from '@/components/nav/topNav.vue'
import LeftNav from '@/components/nav/leftNav.vue'
import Home from '@/views/home.vue'
import Dashboard from '@/views/workbench/dashboard.vue'
import MySettings from '@/views/workbench/mySettings.vue'
import Mission from '@/views/workbench/mission/mission.vue'
import Plan from '@/views/workbench/plan.vue'
import Maillist from '@/views/workbench/maillist.vue'
import EnterpriseList from '@/views/enterprise/index.vue'
import EnterpriseAdd from '@/views/enterprise/add.vue'
import EnterpriseDetail from '@/views/enterprise/detail.vue'
import EnterpriseValidate from '@/views/enterprise/validate.vue'
import VehicleManage from '@/views/vehicle/index.vue'
import DeptManager from '@/views/dept/index.vue'
Vue.use(Router)
let router = new Router({
routes: [
{
path: '/',
type: 'home', // 根據(jù)type區(qū)分不同模塊(頂部導(dǎo)航)
name: 'home', // 根據(jù)name區(qū)分不同子模塊(左側(cè)導(dǎo)航)
redirect: '/dashboard',
component: Home,
children: [
{
path: '/dashboard',
name: '首頁(yè)', // 當(dāng)前路由的name(導(dǎo)航欄顯示文字)
components: {
default: Dashboard,
top: TopNav,
aside: LeftNav
},
leaf: true, // 只有一個(gè)節(jié)點(diǎn)
iconCls: 'iconfont icon-home', // 圖標(biāo)樣式class
menuShow: true
},
{
path: '/mySet',
components: {
default: MySettings,
top: TopNav,
aside: LeftNav
},
name: '我的設(shè)置',
iconCls: 'el-icon-menu',
menuShow: true,
children: [
{ path: '/mySet/plan', component: Plan, name: '行程計(jì)劃', menuShow: true },
{ path: '/mySet/mission', component: Mission, name: '我的任務(wù)', menuShow: true },
{ path: '/mySet/maillist', component: Maillist, name: '通訊錄', menuShow: true }
]
}
]
},
{
path: '/enterpriseManager',
type: 'enterprise',
name: 'enterprise',
component: Home,
redirect: '/enterprise/list',
menuShow: true,
children: [
{
path: '/enterprise/list',
name: '企業(yè)信息',
components: {
default: EnterpriseList,
top: TopNav,
aside: LeftNav
},
leaf: true,
iconCls: 'el-icon-setting',
menuShow: true
},
{
path: '/enterprise/detail',
name: '企業(yè)詳情',
components: {
default: EnterpriseDetail,
top: TopNav,
aside: LeftNav
},
leaf: true,
iconCls: 'el-icon-setting',
menuShow: false
},
{
path: '/enterprise/add',
name: '添加企業(yè)',
components: {
default: EnterpriseAdd,
top: TopNav,
aside: LeftNav
},
leaf: true,
iconCls: 'el-icon-menu',
menuShow: true
},
{
path: '/enterprise/validate',
name: '企業(yè)認(rèn)證',
components: {
default: EnterpriseValidate,
top: TopNav,
aside: LeftNav
},
leaf: true,
iconCls: 'el-icon-menu',
menuShow: true
}
]
},
{
path: '/vehicleManager',
type: 'enterprise',
name: 'vehicle',
component: Home,
redirect: '/vehicle/list',
menuShow: true,
children: [
{
path: '/vehicle/list',
name: '車輛信息',
components: {
default: VehicleManage,
top: TopNav,
aside: LeftNav
},
leaf: true, // 只有一個(gè)節(jié)點(diǎn)
iconCls: 'iconfont icon-home', // 圖標(biāo)樣式class
menuShow: true
}
]
},
{
path: '/deptManager',
type: 'enterprise',
name: 'dept',
component: Home,
redirect: '/dept/list',
menuShow: true,
children: [
{
path: '/dept/list',
name: '部門(mén)信息',
components: {
default: DeptManager,
top: TopNav,
aside: LeftNav
},
leaf: true, // 只有一個(gè)節(jié)點(diǎn)
iconCls: 'iconfont icon-home', // 圖標(biāo)樣式class
menuShow: true
}
]
}
]
});特別說(shuō)明:
這里的路由對(duì)象router ,設(shè)置的是最多三級(jí),一級(jí)路由主要對(duì)應(yīng)的是頂部導(dǎo)航和其他無(wú)子頁(yè)面的路由,二級(jí)和三級(jí)路由分別對(duì)應(yīng)的是左側(cè)導(dǎo)航的一級(jí)和二級(jí)菜單(比如三級(jí)路由對(duì)應(yīng)的就是左側(cè)導(dǎo)航的二級(jí)菜單),二級(jí)路由設(shè)置leaf屬性,值為true表明該路由下沒(méi)有子菜單(如果該路由下的某頁(yè)面不顯示在左側(cè)導(dǎo)航,不算子菜單)。
2、home.vue,這里分別有name=top,aside,default三個(gè)視圖,top代表頂部導(dǎo)航,aside代表左側(cè)導(dǎo)航,剩下的default就是默認(rèn)視圖,代表右側(cè)內(nèi)容區(qū)
<template>
<el-row class="container">
<!--頭部-->
<el-col :span="24"><router-view name="top"></router-view></el-col>
<el-col :span="24" class="main">
<!--左側(cè)導(dǎo)航-->
<router-view name="aside"></router-view>
<!--右側(cè)內(nèi)容區(qū)-->
<section class="content-container">
<div class="grid-content bg-purple-light">
<el-col :span="24" class="content-wrapper">
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</el-col>
</div>
</section>
</el-col>
</el-row>
</template>
<script>
export default {
name: 'home',
data () {
return {
loading: false
}
}
}
</script>3、topNav.vue 是頂部導(dǎo)航菜單的代碼
<template>
<el-row class="container">
<!--頭部-->
<el-col :span="24" class="topbar-wrap">
<div class="topbar-logo topbar-btn">
<a href="/" rel="external nofollow" rel="external nofollow" ><img src="../../assets/logo.png" style="padding-left:8px;"></a>
</div>
<div class="topbar-logos">
<a href="/" rel="external nofollow" rel="external nofollow" style="color: #fff;">車車綜合管理</a>
</div>
<div class="topbar-title">
<!-- 注意:這里就是topNavState作用之處,根據(jù)當(dāng)前路由所在根路由的type值判斷顯示不同頂部導(dǎo)航菜單 -->
<el-row v-show="$store.state.topNavState==='home'">
<el-col :span="24">
<el-menu :default-active="defaultActiveIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" :router="true">
<el-menu-item index="/">工作臺(tái)</el-menu-item>
<el-menu-item index="/enterpriseManager">企業(yè)管理</el-menu-item>
<el-menu-item index="/orderManager">訂單管理</el-menu-item>
<el-menu-item index="/systemManager">系統(tǒng)管理</el-menu-item>
</el-menu>
</el-col>
</el-row>
<el-row v-show="$store.state.topNavState==='enterprise'">
<el-col :span="24">
<el-menu :default-active="defaultActiveIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" :router="true">
<el-menu-item index="/enterpriseManager">企業(yè)信息</el-menu-item>
<el-menu-item index="/vehicleManager">車輛信息</el-menu-item>
<el-menu-item index="/deptManager">組織架構(gòu)</el-menu-item>
</el-menu>
</el-col>
</el-row>
</div>
<div class="topbar-account topbar-btn">
<el-dropdown trigger="click">
<span class="el-dropdown-link userinfo-inner">
<i class="iconfont icon-user"></i> {{nickname}} <i class="el-icon-caret-bottom"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<div @click="jumpTo('/user/profile')"><span style="color: #555;font-size: 14px;">個(gè)人信息</span></div>
</el-dropdown-item>
<el-dropdown-item>
<div @click="jumpTo('/user/changepwd')"><span style="color: #555;font-size: 14px;">修改密碼</span></div>
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">退出登錄</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-col>
</el-row>
</template>
<script>
import 'element-ui/lib/theme-chalk/display.css';
import {road} from '../../road.js'
export default {
data(){
return {
loading: false,
companyName: '',
nickname: '',
defaultActiveIndex: '/',
homeMenu: false,
messageCount: 5
}
},
created() {
road.$on('setNickName', (text) => {
this.nickname = text;
});
road.$on('goto', (url) => {
if(url === "/login") {
localStorage.removeItem('access-user');
this.$router.push(url);
}
});
// 組件創(chuàng)建完后獲取數(shù)據(jù)
this.fetchNavData();
},
methods: {
jumpTo(url){
this.$router.push(url); //用go刷新
},
handleSelect(index){
this.defaultActiveIndex = index;
},
fetchNavData () { // 初始化菜單激活項(xiàng)
let cur_path = this.$route.path; //獲取當(dāng)前路由
let routers = this.$router.options.routes; // 獲取路由對(duì)象
let nav_type = "", nav_name = "";
for (var i = 0; i < routers.length; i++) {
let children = routers[i].children;
if(children){
for (let j = 0; j < children.length; j++) {
if (children[j].path === cur_path) {
nav_type = routers[i].type;
nav_name = routers[i].name;
break;
}
// 如果該菜單下還有子菜單
if(children[j].children) {
let grandChildren = children[j].children;
for(let z=0; z<grandChildren.length; z++) {
if(grandChildren[z].path === cur_path) {
nav_type = routers[i].type;
nav_name = routers[i].name;
break;
}
}
}
}
}
}
this.$store.state.topNavState = nav_type;
this.$store.state.leftNavState = nav_name;
if(nav_type == "home"){
this.defaultActiveIndex = "/";
} else {
this.defaultActiveIndex = "/" + nav_name + "Manager";
}
},
logout(){
//logout
this.$confirm('確認(rèn)退出嗎?', '提示', {
confirmButtonClass: 'el-button--warning'
}).then(() => {
//確認(rèn)
localStorage.removeItem('access-user');
road.$emit('goto', '/login');
}).catch(() => {});
}
},
mounted() {
let user = window.localStorage.getItem('access-user');
if (user) {
user = JSON.parse(user);
this.nickname = user.nickname || '';
this.companyName = user.companyName || '';
}
},
watch: {
'$route': function(to, from){ // 路由改變時(shí)執(zhí)行
//console.info("to.path:" + to.path);
this.fetchNavData();
}
}
}
</script>注意fetchNavData()這個(gè)方法,主要是根據(jù)當(dāng)前跳轉(zhuǎn)的路由,去找到這個(gè)路由對(duì)應(yīng)的type(對(duì)應(yīng)頂部導(dǎo)航欄的分類)和name(對(duì)應(yīng)左側(cè)導(dǎo)航欄的分類),然后保存type和name到$store中,這樣在topNav.vue組件可以根據(jù)$store中的type顯示相應(yīng)的菜單,同樣在leftNav.vue組件就可以取到這個(gè)name值并顯示相應(yīng)的左側(cè)菜單欄了。另外,里面的top和aside是命名視圖,分別對(duì)應(yīng)頂部導(dǎo)航組件和左側(cè)導(dǎo)航組件。
補(bǔ)充:topNavState和leftNavState這兩個(gè)狀態(tài)就是精髓所在,分別控制頂部和左側(cè)導(dǎo)航展示對(duì)應(yīng)模塊菜單,這兩個(gè)狀態(tài)是在vuex配置文件store.js中設(shè)置的
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
collapsed: false, // 左側(cè)導(dǎo)航折疊狀態(tài)
topNavState: 'home',
leftNavState: 'dispatch'
}
export default new Vuex.Store({
state
})store.js文件在main.js中引入:
import store from './store.js'
new Vue({
router,
store,
el: '#app',
render: h => h(App)
})4、leftNav.vue 左側(cè)導(dǎo)航欄(這里的左側(cè)菜單欄最多有兩級(jí)菜單)
<template>
<!--左側(cè)導(dǎo)航-->
<aside :class="{showSidebar:!collapsed}">
<!--展開(kāi)折疊開(kāi)關(guān)-->
<div class="menu-toggle" @click.prevent="collapse">
<i class="iconfont icon-outdent" v-show="!collapsed" title="收起"></i>
<i class="iconfont icon-indent" v-show="collapsed" title="展開(kāi)"></i>
</div>
<!--導(dǎo)航菜單-->
<el-menu :default-active="$route.path" router :collapse="collapsed" ref="leftNavigation">
<template v-for="(issue,index) in $router.options.routes">
<!-- 注意:這里就是leftNavState狀態(tài)作用之處,當(dāng)該值與router的根路由的name相等時(shí)加載相應(yīng)菜單組 -->
<template v-if="issue.name === $store.state.leftNavState">
<template v-for="(item,index) in issue.children">
<el-submenu v-if="!item.leaf" :index="index+''" v-show="item.menuShow">
<template slot="title"><i :class="item.iconCls"></i><span slot="title">{{item.name}}</span></template>
<el-menu-item v-for="term in item.children" :key="term.path" :index="term.path" v-if="term.menuShow"
:class="$route.path==term.path?'is-active':''">
<i :class="term.iconCls"></i><span slot="title">{{term.name}}</span>
</el-menu-item>
</el-submenu>
<el-menu-item v-else-if="item.leaf" :index="item.path"
:class="$route.path==item.path?'is-active':''" v-show="item.menuShow">
<i :class="item.iconCls"></i><span slot="title">{{item.name}}</span>
</el-menu-item>
</template>
</template>
</template>
</el-menu>
</aside>
</template>
<script>
export default {
name: 'leftNav',
data () {
return {
loading: false,
collapsed: this.$store.state.collapsed,
}
},
methods: {
//折疊導(dǎo)航欄
collapse: function () {
this.collapsed = !this.collapsed;
this.$store.state.collapsed = this.collapsed;
},
// 左側(cè)導(dǎo)航欄根據(jù)當(dāng)前路徑默認(rèn)打開(kāi)子菜單(如果當(dāng)前是二級(jí)菜單,則父級(jí)子菜單默認(rèn)打開(kāi))
defaultLeftNavOpened () {
let cur_path = this.$route.path; //獲取當(dāng)前路由
let routers = this.$router.options.routes; // 獲取路由對(duì)象
let subMenuIndex = '', needOpenSubmenu = false;
for (let i = 0; i < routers.length; i++) {
let children = routers[i].children;
if(children){
for (let j = 0; j < children.length; j++) {
if(children[j].path === cur_path) {
break;
}
// 如果該菜單下還有子菜單
if(children[j].children && !children[j].leaf) {
let grandChildren = children[j].children;
for(let z=0; z<grandChildren.length; z++) {
if(grandChildren[z].path === cur_path) {
subMenuIndex = j;
needOpenSubmenu = true;
break;
}
}
}
}
}
}
if(this.$refs['leftNavigation'] && needOpenSubmenu) {
this.$refs['leftNavigation'].open(subMenuIndex); // 打開(kāi)子菜單
}
},
},
watch: {
'$route': function(to, from){ // 路由改變時(shí)執(zhí)行
//console.info("to.path:" + to.path);
}
},
mounted() {
this.defaultLeftNavOpened();
},
}
</script>5、如果左側(cè)導(dǎo)航含有二級(jí)菜單,
比如“我的設(shè)置(/mySet)”中,含有三個(gè)子菜單:

路由配置如下:(具體文件路徑及配置請(qǐng)看router/index.js)
{
path: '/mySet',
components: {
default: MySettings,
top: TopNav,
aside: LeftNav
},
name: '我的設(shè)置',
iconCls: 'el-icon-menu',
menuShow: true,
children: [
{ path: '/mySet/plan', component: Plan, name: '行程計(jì)劃', menuShow: true },
{ path: '/mySet/mission', component: Mission, name: '我的任務(wù)', menuShow: true },
{ path: '/mySet/maillist', component: Maillist, name: '通訊錄', menuShow: true }
]
}此時(shí),我們只需在父級(jí)菜單對(duì)應(yīng)視圖(MySettings)中添加一個(gè)router-view即可:
<template> <router-view></router-view> </template>
6、整體效果圖:

附上github地址:https://github.com/yqrong/vvproject
到此這篇關(guān)于ElementUI+命名視圖實(shí)現(xiàn)復(fù)雜頂部和左側(cè)導(dǎo)航欄的文章就介紹到這了,更多相關(guān)Element頂部和左側(cè)導(dǎo)航欄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目中使用pinyin轉(zhuǎn)換插件方式
這篇文章主要介紹了vue項(xiàng)目中使用pinyin轉(zhuǎn)換插件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
基于Vue的SPA動(dòng)態(tài)修改頁(yè)面title的方法(推薦)
這篇文章主要介紹了基于Vue的SPA動(dòng)態(tài)修改頁(yè)面title的方法,需要的朋友可以參考下2018-01-01
詳解Vue如何將多個(gè)空格被合并顯示成一個(gè)空格
這篇文章主要為大家詳細(xì)介紹了在Vue中如何將多個(gè)空格被合并顯示成一個(gè)空格,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
淺談vue項(xiàng)目4rs vue-router上線后history模式遇到的坑
今天小編就為大家分享一篇淺談vue項(xiàng)目4rs vue-router上線后history模式遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
如何實(shí)現(xiàn)echarts markline標(biāo)簽名顯示自己想要的
這篇文章主要介紹了實(shí)現(xiàn)echarts markline標(biāo)簽名顯示自己想要的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
vue3+elementplus 樹(shù)節(jié)點(diǎn)過(guò)濾功能實(shí)現(xiàn)
樹(shù)節(jié)點(diǎn)所展示的街道是讀取的成都市金牛區(qū)的范圍邊界線的json文件,街道下對(duì)應(yīng)內(nèi)容市通過(guò)fetch調(diào)用接口獲取的內(nèi)容,通過(guò)mapTreeData函數(shù)循環(huán)遍歷,對(duì)數(shù)據(jù)進(jìn)行處理,這篇文章主要介紹了vue3+elementplus 樹(shù)節(jié)點(diǎn)過(guò)濾功能實(shí)現(xiàn),需要的朋友可以參考下2024-05-05
vue.js滾動(dòng)條插件vue-scroll的基本用法
在移動(dòng)端或PC,頁(yè)面的部分內(nèi)容常常需要我們讓其在頁(yè)面滾動(dòng),這篇文章主要給大家介紹了關(guān)于vue.js滾動(dòng)條插件vue-scroll的基本用法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12

