为了让大家可以继续看下去,代码展示效果我先给出来
https://htmlzhoyan.github.io/ElementUi/#/ele/elc/%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86
我这里要实现 Vue 2.0 的桌面端组件库Element中的侧边栏内容动态生成,换句话说,我并不知道侧边栏菜单里会有多少个子选项,所以我这样设计
目录结构如下:
我这边使用了组件里面再次调用组件的方法。
所以 我这样先声明个组件 eleTemplate.vue
<template>
<div class="navMenu">
<label v-for="navMenu in navMenus">
<router-link :to="{ name: 'elc', params: {id:navMenu.entity.name} }">
<el-menu-item v-if="navMenu.childs==null&&navMenu.entity&&navMenu.entity.state==='ENABLE'"
:key="navMenu.entity.id" :data="navMenu" :index="navMenu.entity.name" :route="navMenu.entity.value">
<i :class="navMenu.entity.icon"></i>
<span slot="title">{{navMenu.entity.alias}}</span>
</el-menu-item>
</router-link>
<el-submenu v-if="navMenu.childs&&navMenu.entity&&navMenu.entity.state==='ENABLE'"
:key="navMenu.entity.id" :data="navMenu" :index="navMenu.entity.name">
<template slot="title">
<i :class="navMenu.entity.icon"></i>
<span> {{navMenu.entity.alias}}</span>
</template>
<NavMenu :navMenus="navMenu.childs"></NavMenu>
</el-submenu>
</label>
</div>
</template>
<script>
export default {
name: 'NavMenu',
props: ['navMenus'],
data() {
return {}
},
methods: {}
}
</script>
<style scoped>
a{
text-decoration:none
}
</style>
然后我在父组件里调用它,这里我使用了router-view来展示子路由里的页面效果,同时我为了实现路由进来的时候去触发侧边栏的指向,我在el-menu里添加了default-active
<template lang="html">
<div class="">
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<!--左侧菜单组件-->
<el-menu
:default-active="isId"
@select="handleSelect"
class="el-menu-vertical-demo"
background-color="#F0F6F6"
text-color="#3C3F41"
active-text-color="#f60">
<NavMenu :navMenus="totalList"></NavMenu>
</el-menu>
</el-aside>
<el-container>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import config from './config'
import NavMenu from './eleTemplate';
export default {
data() {
return{
totalList:[],
isId:"权限管理"
}
},
methods: {
handleSelect(key,keyPath){
console.log(key,keyPath)
}
},
components: {
NavMenu
},
beforeRouteEnter (to, from, next) {
console.log("我从哪里来",to.params.id,from)
var self = this
next(vm=>{
vm.isId = to.params.id
})
},
watch:{
$route(to,from){
this.isId = to.params.id
}
},
created(){
this.totalList = config.childs
},
}
</script>
<style lang="css">
</style>
其中 我为了模拟数据,引入config.js,后期是通过后端返回的数据来实现的
let config = {
"entity": null,
"childs": [
{
"entity": {
"id": 1,
"parentMenuId": 0,
"name": "系统管理",
"icon": "el-icon-message\r\n",
"alias": "系统管理",
"state": "ENABLE",
"sort": 0,
"value": null,
"type": "NONE",
"createUserId": 1
},
"childs": [
{
"entity": {
"id": 3,
"parentMenuId": 1,
"name": "权限管理",
"icon": "el-icon-loading",
"alias": "权限管理",
"state": "ENABLE",
"sort": 0,
"value": "/system/auth",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 4,
"parentMenuId": 1,
"name": "角色管理",
"icon": "el-icon-bell",
"alias": "角色管理",
"state": "ENABLE",
"sort": 1,
"value": "/system/role",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 2,
"parentMenuId": 1,
"name": "菜单管理",
"icon": "el-icon-edit",
"alias": "菜单管理",
"state": "ENABLE",
"sort": 2,
"value": "/system/menu",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 5,
"parentMenuId": 1,
"name": "分组管理",
"icon": "el-icon-mobile-phone\r\n",
"alias": "分组管理",
"state": "ENABLE",
"sort": 3,
"value": "/system/group",
"type": "LINK",
"createUserId": 1
},
"childs": null
}
]
},
{
"entity": {
"id": 6,
"parentMenuId": 0,
"name": "用户管理",
"icon": "el-icon-news",
"alias": "用户管理",
"state": "ENABLE",
"sort": 1,
"value": null,
"type": "NONE",
"createUserId": 1
},
"childs": [
{
"entity": {
"id": 7,
"parentMenuId": 6,
"name": "帐号管理",
"icon": "el-icon-phone-outline\r\n",
"alias": "帐号管理",
"state": "ENABLE",
"sort": 0,
"value": "",
"type": "NONE",
"createUserId": 1
},
"childs": [
{
"entity": {
"id": 14,
"parentMenuId": 7,
"name": "邮箱管理",
"icon": "el-icon-sold-out\r\n",
"alias": "邮箱管理",
"state": "ENABLE",
"sort": 0,
"value": "/content/email",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 13,
"parentMenuId": 7,
"name": "密码管理",
"icon": "el-icon-service\r\n",
"alias": "密码管理",
"state": "ENABLE",
"sort": 1,
"value": "/content/pass",
"type": "LINK",
"createUserId": 1
},
"childs": null
}
]
},
{
"entity": {
"id": 8,
"parentMenuId": 6,
"name": "积分管理",
"icon": "el-icon-picture",
"alias": "积分管理",
"state": "ENABLE",
"sort": 1,
"value": "/user/integral",
"type": "LINK",
"createUserId": 1
},
"childs": null
}
]
},
{
"entity": {
"id": 9,
"parentMenuId": 0,
"name": "内容管理",
"icon": "el-icon-rank",
"alias": "内容管理",
"state": "ENABLE",
"sort": 2,
"value": null,
"type": "NONE",
"createUserId": 1
},
"childs": [
{
"entity": {
"id": 10,
"parentMenuId": 9,
"name": "分类管理",
"icon": "el-icon-printer",
"alias": "分类管理",
"state": "ENABLE",
"sort": 0,
"value": "/content/classify",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 11,
"parentMenuId": 9,
"name": "文章管理",
"icon": "el-icon-star-on",
"alias": "文章管理",
"state": "ENABLE",
"sort": 1,
"value": "/content/article",
"type": "LINK",
"createUserId": 1
},
"childs": null
},
{
"entity": {
"id": 12,
"parentMenuId": 9,
"name": "评论管理",
"icon": "el-icon-share",
"alias": "评论管理",
"state": "ENABLE",
"sort": 2,
"value": "/content/comment",
"type": "LINK",
"createUserId": 1
},
"childs": null
}
]
}
]
}
export default config
和附加内容elc.vue,来填充contain内容。我实现了tab选项的增和删,同时,添加了如果重复去跳转之前添加的tab,删除tab之前有bug,这次修改后,通过监听路由改动,保证路由实时改动,侧边栏也可以进行改变
<template lang="html">
<div>
<div style="margin-bottom: 20px;">
</div>
<el-tabs v-model="editableTabsValue2" type="card" closable @tab-remove="removeTab">
<el-tab-pane
v-for="(item, index) in editableTabs2"
:key="item.name"
:label="item.title"
:name="item.name"
>
{{item.title}}
</el-tab-pane>
</el-tabs>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data(){
return {
btn:true,
item:{
date: '2018-11-11',
name: 'OnePiece',
address: '郑州市高新区推进城',
},
editableTabsValue2: '2',
editableTabs2: [],
tabIndex: 0,
tableData: [],
totalList:[],
}
},
methods:{
addTab(targetName) {
this.btn= true
this.editableTabs2.forEach((v,k)=>{
if(v.title==targetName){
this.btn = false;
this.editableTabsValue2 = v.name
}
})
if(this.btn){
let newTabName = ++this.tabIndex + '';
this.editableTabs2.push({
title: targetName,
name: newTabName,
content: targetName
});
this.editableTabsValue2 = newTabName;
}
},
removeTab(targetName) {
let tabs = this.editableTabs2;
let activeName = this.editableTabsValue2;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
this.$router.push({
name: "elc",
params: {
id: nextTab.title
}
});
}
}
});
}
this.editableTabsValue2 = activeName;
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
}
},
created () {
this.tableData = Array(20).fill(this.item);
},
beforeRouteEnter (to, from, next) {
console.log("我从哪里来",to.params.id,from)
var self = this
next(vm=>{
vm.item.name =to.params.id;
vm.addTab(to.params.id);
})
},
watch:{
$route(to,from){
this.item.name =this.$route.params.id;
this.addTab(to.params.id);
}
},
}
</script>
<style lang="css">
</style>
路由的内容
这样我就实现了,可以根据后端返回数据来动态加载数据。