Usar component:
<menu
:items="items"
:visible="true"
title="PredictorApp - Teams">
</menu>Itens do menu:
data () {
return {
items: [
{
value: 'Home',
path: '/home'
},
{
value: 'Criar',
path: '/create'
},
{
value: 'Has Submenu',
children: [
{
value: 'Outro sub',
children: [
{
value: 'Outra pagina',
path: '/page'
}
]
},
{
value: 'Página X',
path: '/pagex'
},
{
value: 'Submenu irmão',
children: [
{
value: 'Página Y',
path: '/pagey'
}
]
}
]
}
]
}
}
Menu Component:
<template>
<aside
id="menu"
:class="{'visible': isVisible}"
:style="{'padding-right': width}"
:click="togglePadding">
<div
class="menu-inner"
:style="{'width': definedWidth}">
<button
type="button"
class="toggle-menu-button btn"
v-on:click="toggleVisible">
<i class="glyphicon glyphicon-menu-hamburger"></i>
</button>
<h1>
{{ title }}
</h1>
<div class="menu-content">
<slot></slot>
<ul class="menu-list">
<item :model="items"></item>
</ul>
</div>
</div>
</aside>
</template>
<script>
import Item from './Item'
export default {
props: {
'items': {
type: Array,
default: []
},
'title': {
type: String,
default: 'Menu'
},
'visible': {
type: Boolean,
default: true
}
},
data () {
return {
isVisible: this.visible,
definedWidth: null,
width: '300px'
}
},
methods: {
toggleVisible: function (event) {
this.isVisible = !this.isVisible
},
togglePadding: function (event) {
this.width = '50px'
if (this.isVisible) {
this.width = this.definedWidth
}
}
},
created () {
this.definedWidth = this.width
},
components: {
Item
}
}
</script>
<style>
#menu {
height: 100vh;
margin-right: 20px;
position: fixed;
}
.menu-inner {
background-color: #ddd;
height: 100%;
left: 0;
position: absolute;
top: 0;
transform: translateX(-83%);
transition: all .2s;
width: 100%;
vertical-align: top;
}
#menu.visible .menu-inner {
transform: translateX(0);
}
.btn.toggle-menu-button {
color: #666;
font-size: 1.2em;
line-height: 1;
position: absolute;
right: 5px;
top: 5px;
}
#menu h1 {
font-size: 1.5em;
font-weight: bold;
margin-left: 20px;
margin-top: 0;
padding-top: 10px;
text-align: left;
}
#menu .menu-list {
padding: 0;
}
#menu .menu-content {
display: none;
margin: 40px auto 0;
width: 90%;
}
#menu.visible .menu-content {
display: block;
}
.menu-item,
.menu-item.has-submenu > div {
color: #2c3e50;
display: block;
font-size: 1.6rem;
list-style: none;
text-align: left;
width: 100%;
}
.menu-item a,
.menu-item.has-submenu > div {
display: block;
width: 100%;
height: 100%;
padding: 2% 2% 2% 10%;
color: inherit;
}
.has-submenu ul {
padding: 0;
}
.has-submenu ul li {
padding-left: 15px;
}
.has-submenu > div {
cursor: pointer;
}
#menu.visible .menu-item:not(.has-submenu):hover a,
#menu.visible .menu-item.has-submenu > div:hover,
#menu.visible .menu-item a.active {
background-color: #2c3e50;
color: #fff;
text-decoration: none;
}
#menu + * {
margin-left: 50px;
}
#menu.visible + * {
margin-left: 330px;
}
</style>Item Component:
<template>
<li
v-for="item in model"
class="menu-item"
:class="{'has-submenu': isSubmenu(item)}">
<a
v-link="{ path: item.path, activeClass: 'active' }"
v-if="!isSubmenu(item)">
{{ item.value }}
</a>
<div
v-else
@click="toggle(item)">
{{ item.value }}
<span class="show-submenu">
[{{ isOpened(item) ? '-' : '+' }}]
</span>
</div>
<ul
v-show="isOpened(item)"
v-if="isSubmenu(item)">
<item :model="item.children"></item>
</ul>
</li>
</template>
<script>
export default {
name: 'Item',
props: {
model: Array
},
data () {
return {
openedItems: []
}
},
methods: {
isOpened: function (item) {
return this.openedItems.indexOf(item) !== -1
},
_openOrClose: function (item) {
if (this.isOpened(item)) {
this.openedItems.splice(this.openedItems.indexOf(item), 1)
return true
}
this.openedItems.push(item)
},
isSubmenu: function (item) {
return item.children && item.children.length
},
toggle: function (item) {
if (!this.isSubmenu(item)) {
return false
}
this._openOrClose(item)
}
}
}
</script>