Vue-router 结合 element-ui 制作动态导航栏 + 面包屑
效果图如下:主要思路:一开始我的想法是根据左侧导航栏的点击事件动态的改变上方的面包屑,但后来发现如果直接通过 URL 访问的话导航栏和面包屑都是处于初始状态的。因此我想到通过 route 的值同时改变导航栏和面包屑。首先,我们定义 route 文件,注意将 Router 的模式设为 history,否则跳转时 URL 上会带有 # 符号,导致获取到的 route 值不正确,代码如下...
效果图如下:
主要思路:
一开始我的想法是根据左侧导航栏的点击事件动态的改变上方的面包屑,但后来发现如果直接通过 URL 访问的话导航栏和面包屑都是处于初始状态的。因此我想到通过 router 的值同时改变导航栏和面包屑。
首先,我们定义 router 文件,注意将 Router 的模式设为 history,否则跳转时 URL 上会带有 # 符号,导致获取到的 route 值不正确,代码如下:
router.ts
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: () => import('./views/Home.vue'),
},
{
name: '1',
path: ':id',
component: () => import('./views/Component1.vue'),
children: [
{
path: '/1-1',
name: '1-1',
component: () => import('./views/Component1-1.vue'),
},
{
path: '/1-2',
name: '1-2',
component: () => import('./views/Component1-1.vue'),
},
{
path: '/1-3',
name: '1-3',
component: () => import('./views/Component1-1.vue'),
},
],
},
],
});
导航栏我使用的是 el-menu 组件,它有一个属性是 default-active,结合 el-submenu 定义的 index 属性,可以很方便的与 route 同步,代码如下:
NavMenu.vue
<template>
<div class="container">
<el-row class="container">
<el-col :span="24" class="container">
<el-menu :router=true :default-active="$route.name" class="el-menu-vertical-demo container">
<el-submenu index="1">
<template slot="title">
<span>title1</span>
</template>
<el-menu-item index="1-1">title1-1</el-menu-item>
<el-menu-item index="1-2">title1-2</el-menu-item>
<el-menu-item index="1-3">title1-3</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class NavMenu extends Vue {}
</script>
面包屑使用的是 el-breadcrumb 组件,为了与 route 同步,需要 watch $route
的值,$route.matched
得到的是一个数组,刚好可以处理后得到面包屑的标题的数组,代码如下:
BreadCrumb.vue
<template>
<div>
<el-breadcrumb separator-class="el-icon-arrow-right" class="breadcrumb">
<el-breadcrumb-item><a href="/">首页</a></el-breadcrumb-item>
<el-breadcrumb-item v-for="bread in breadList" v-bind:key="bread">
{{ breadsName[bread] }}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
<script lang="ts">
import { Provide, Component, Watch, Prop, Vue } from 'vue-property-decorator';
@Component
export default class BreadCrumb extends Vue {
@Provide() private breadsName: { [index: string]: string } = {
'1': 'title1',
'1-1': 'title1-1',
'1-2': 'title1-2',
'1-3': 'title1-3',
};
@Provide() private breadList: string[] = [];
private created() {
this.getBreadList();
}
@Watch('$route')
private getBreadList() {
this.breadList = [];
for (const routeInfo of this.$route.matched) {
if (typeof routeInfo.name === 'string' && routeInfo.name !== 'home') {
this.breadList.push(routeInfo.name);
}
}
}
}
</script>
<style lang="less">
.breadcrumb {
margin-bottom: 20px;
}
</style>
两个组件完成后,我们需要把它们引入到主页面中,代码如下:
App.vue
<template>
<div id="app">
<el-container class="container" >
<el-container class="container">
<el-aside class="aside">
<NavMenu/>
</el-aside>
<el-main class="main">
<BreadCrumb/>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Provide, Component } from 'vue-property-decorator';
import NavMenu from '@/components/NavMenu.vue';
import BreadCrumb from '@/components/BreadCrumb.vue';
@Component({
components: {
NavMenu, BreadCrumb,
},
})
export default class App extends Vue {}
</script>
<style lang="less">
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
}
#app {
height: 100%;
}
.container {
height: 100%;
}
.aside {
height: 100%;
width: 15%;
min-width: 200px;
max-width: 240px;
}
</style>
需要注意的是,即使层级1是没有页面的,但是层级1-1的组件是渲染到层级1的组件中的,一开始我没有创建 Component1
这个组件,只在 APP.vue 添加了 <router-view/>
发现渲染不出组件 Component1-1
。
这两个组件的内容如下,需要自己填充其他内容。
Component1.vue
<template>
<div>
<router-view/>
</div>
</template>
Component1-1.vue
<template>
<div>
<h1>This is a page</h1>
</div>
</template>
更多推荐
所有评论(0)