本章的最終效果
這章的開(kāi)發(fā)在admin子項(xiàng)目中進(jìn)行件舵。這里我們?cè)趐roject/admin中創(chuàng)建文件App.vue。內(nèi)容如vue合家福實(shí)例(2):使用element-ui el-scrollbar中的脯厨,建立一個(gè)項(xiàng)目的頁(yè)面框架铅祸。統(tǒng)一的菜單和頂部狀態(tài)欄。
在開(kāi)發(fā)中俄认,要增加一個(gè)頁(yè)面个少。我是先寫(xiě)一個(gè)簡(jiǎn)單的組件(.vue)文件,然后配置路由眯杏。接下去是修改菜單(這樣的情況下夜焦,一般菜單會(huì)建立一個(gè)組件)。那么岂贩,如果路由配置好后就可以增加到菜單中茫经,即菜單是根據(jù)路由生成的,這樣修改路由就不用再去改菜單的代碼萎津。想想挺酷的卸伞。
目錄結(jié)構(gòu):
我們?cè)诩t框中的文件目錄進(jìn)行工作。
BhLayout>src>menu-item.vue (一個(gè)菜單項(xiàng)組件锉屈,對(duì)element-ui的菜單組件進(jìn)行再封裝)
菜單的代碼在App.vue中荤傲,routers.js是路由配置文件。
App.vue:
<script>
import _ from 'lodash'
import {BhMenuItem} from '@/components/BhLayout' // 加入菜單項(xiàng)組件
export default {
name: 'app',
components: {
BhMenuItem
},
data () {
return {
isCollapse: false,
asideWidth: '230px',
vmenus: [],
defActive: this.activePath()
}
},
created () {},
watch: {
$route () {
this.defActive = this.activePath()
this.setPageTitle()
}
},
methods: {
// 改變菜單欄的寬度
changeCollapse () {
this.isCollapse = !this.isCollapse
this.$emit('collapse-change', this.isCollapse)
if (this.isCollapse) {
this.asideWidth = '65px'
} else {
this.asideWidth = '230px'
}
},
// 設(shè)置頁(yè)面標(biāo)題
setPageTitle () {
let path = this.$route.path
let pathArr = _.split(path, '/')
let l = pathArr.length
let menus = this.$router.options.routes
if (_.isEmpty(menus) || l < 2) {
return
}
let ts = ['vue全家福']
let i = 1
let children = menus
while (i < l) {
path = _.join(_.slice(pathArr, 0, i + 1), '/')
let index = _.findIndex(children, menu => {
let menuPath = menu.path
let i = menuPath.indexOf('/:')
if (i > 0) {
menuPath = menuPath.substring(0, i)
}
return menuPath === path
})
if (index < 0) {
break
}
if (!children[index]) {
break
}
if (children[index]['text']) {
ts.push(children[index]['text'])
}
if (!children[index]['children'] || _.isEmpty(children[index]['children'])) {
break
}
children = children[index]['children']
i++
}
this.title = _.clone(ts)
},
// 計(jì)算菜單當(dāng)前選中的路徑
activePath () {
let path = this.$route.path
let pathArr = _.split(path, '/')
let l = pathArr.length
if (l <= 2) {
return path
}
let menus = this.$router.options.routes
if (_.isEmpty(menus)) {
return path
}
let i = 1
let children = menus
while (i < l) {
path = _.join(_.slice(pathArr, 0, i + 1), '/')
let index = _.findIndex(children, {'path': path})
if (index < 0) {
break
}
if (!children[index]) {
break
}
if (children[index]['hasChildren'] === false || !children[index]['children'] || _.isEmpty(children[index]['children'])) {
break
}
children = children[index]['children']
i++
}
return path
}
}
}
</script>
<template>
<el-container>
<!-- 菜單欄 -->
<el-aside :width="asideWidth">
<el-scrollbar class="default-scrollbar" wrap-class="default-scrollbar__wrap" view-class="default-scrollbar__view">
<div :class="isCollapse ? 'menu-collapsed' : 'menu-expanded'">
<el-menu
:default-active="defActive"
class="el-menu-vertical-demo"
unique-opened
router
:collapse="isCollapse">
<bh-menu-item :menu="item" :key="item.name" v-for="item in $router.options.routes" v-if="item.menu"></bh-menu-item>
</el-menu>
</div>
</el-scrollbar>
</el-aside>
<el-container>
<!-- 右邊上面的欄目 -->
<el-header class="clear">
<div class="collapse-btn" @click.prevent="changeCollapse">
<i class="fas fa-bars" :class="{ rotate90: isCollapse }"></i>
</div>
</el-header>
<!-- 路由容器 -->
<router-view></router-view>
</el-container>
</el-container>
</template>
<style scoped>
.collapse-btn {
float: left;
font-size: 24px;
cursor: pointer;
}
.rotate90 {
filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
</style>
補(bǔ)充說(shuō)明:$router.options.routes(如果在js中是this.$router.options.routes)颈渊。取出當(dāng)前路由內(nèi)容遂黍,即src>project>admin>router>routers.js文件中的內(nèi)容
菜單是通過(guò)$router.options.routes(項(xiàng)目路由)自動(dòng)生成的。下面是路由(routers.js)的內(nèi)容:
import Wrap from '@/components/Wrap.vue'
const routers = [{
path: '/',
name: 'home',
text: '首頁(yè)',
menu: true,
icon: 'fas fa-home',
component: resolve => require(['../views/Home'], resolve)
}, {
path: '/dashboard',
name: 'dashboard',
text: '儀表盤(pán)',
menu: true,
icon: 'fas fa-tachometer-alt',
component: resolve => require(['../views/Dashboard'], resolve)
}, {
path: '/user',
name: 'user',
text: '用戶管理',
menu: true,
hasChildren: true,
icon: 'fas fa-user-cog',
component: Wrap,
children: [{
path: '/user/permission',
name: 'user_permission',
text: '權(quán)限管理',
menu: true,
component: resolve => require(['../views/user/Permission'], resolve)
}, {
path: '/user/role',
name: 'user_role',
text: '角色管理',
menu: true,
component: resolve => require(['../views/user/Role'], resolve)
}, {
path: '/user/user',
name: 'user_user',
text: '用戶管理',
menu: true,
component: resolve => require(['../views/user/User'], resolve)
}]
}]
export default routers
補(bǔ)充說(shuō)明:Wrap.vue文件只是一個(gè)簡(jiǎn)單的路由容器俊嗽,內(nèi)容如下雾家。因?yàn)関ue-cli3項(xiàng)目生成的,如果寫(xiě)component: { template: '<router-view></router-view>' } 會(huì)報(bào)異常绍豁。我的方案是建立一個(gè)組件芯咧,引入。
<script>
export default {
name: 'Wrap'
}
</script>
<template>
<router-view></router-view>
</template>
生成菜單的組件BhMenuItem,關(guān)鍵內(nèi)容如下:
<template>
<component v-bind:is="currentItemComponent" :index="menu.path" :key="menu.path">
<i :class="menu.icon" v-if="menu.icon && !hc"></i><span v-if="!hc" slot="title">{{menu.text}}</span>
<template slot="title" v-if="hc">
<i :class="menu.icon" v-if="menu.icon"></i><span slot="title">{{menu.text}}</span>
</template>
<!-- 這里用了遞歸生成菜單項(xiàng) -->
<bh-menu-item :menu="child" :key="child.name" v-for="child in menu.children" v-if="hc && child.menu"></bh-menu-item>
</component>
</template>
<script>
export default {
name: 'BhMenuItem',
props: {
menu: Object
},
data () {
return {
hc: false
}
},
computed: {
currentItemComponent: function () {
return this.hasChildren() ? 'el-submenu' : 'el-menu-item'
}
},
methods: {
hasChildren () {
this.hc = this.menu.hasChildren !== false && this.menu.children && this.menu.children.length > 0
return this.hc
}
}
}
</script>
補(bǔ)充說(shuō)明:菜單的結(jié)構(gòu)是一棵樹(shù)敬飒,可以一層層深入邪铲。在這里判斷如果菜單項(xiàng)沒(méi)有子菜單的話就用element-ui的el-menu-item組件,如果還有子菜單驶拱,則用el-menu-item霜浴。最后如果有子菜單晶衷,遞歸使用組件蓝纲。
在App.vue用BhMenuItem組件生成菜單樹(shù)。完成后晌纫,菜單如圖:
發(fā)現(xiàn)菜單的圖標(biāo)樣式不合理税迷,這是font awesome圖標(biāo)。下章補(bǔ)充font awesome圖標(biāo)使用方法锹漱,在這里與element-ui 圖標(biāo)的padding不一樣箭养。在全局樣式表中加入樣式:
.el-menu .fa,
.el-menu .fas,
.el-menu .far {
margin-right: 10px;
}
最終效果
點(diǎn)擊圖標(biāo)后收縮菜單。