Если кому интересно, реализовал данную задачу. Весь исполняемый код и шаблон пришлось перенести в компонент Page.vue
Вот листинг кода:
Pages.vue
<template>
<div style="width: 100%; height: 100%">
<slot></slot>
</div>
</template>
<style>
.flexcard {
display: flex;
flex-direction: column;
}
</style>
<script>
export default {
data: () => ({
pages : []
}),
mounted () {
this.initPages()
},
methods: {
initPages() {
this.$children.forEach((child) => {
if (child.$options.name == 'Page'){
this.pages.push(child)
}
})
},
}
}
</script>
Page.vue<template>
<v-card width="100%" class="flexcard" v-if="name==activePage" style="height: 100%">
<v-card-title primary-title style="padding-bottom: 0; padding-top: 0;">
<slot name="breadcrumbs">
<v-breadcrumbs divider="/" class="">
<v-breadcrumbs-item
v-for="item in breadcrumbs"
:key="item.text"
:disabled="item.disabled"
@click.native="activePage=item.page"
class="pa-0"
>
{{ item.text }}
</v-breadcrumbs-item>
</v-breadcrumbs>
</slot>
<v-spacer></v-spacer>
<slot name="toolbar"></slot>
</v-card-title>
<v-card-text class="grow">
<slot></slot>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<slot name="actions"></slot>
</v-card-actions>
</v-card>
</template>
<script>
export default {
data: () => ({
}),
computed:{
name(){
return this.$attrs.name
},
activePage : {
get: function () {
return this.$store.state.activePage
},
set: function (newValue) {
this.$store.dispatch('setActivePage', newValue)
}
},
breadcrumbs(){
if (this.activePage) {
console.log(this.activePage)
let breadcr = this.getBreadcrumb(this.activePage).reverse()
return breadcr
}else{
return []
}
},
},
methods:{
getBreadcrumb(pageName) {
let items = []
let page = this.getPageByName(pageName)
if (page) {
items.push({
text: page.$attrs.title,
page: page.$attrs.name
})
if (page.$attrs.parent) {
let parentItem = this.getBreadcrumb(page.$attrs.parent)
items = items.concat(parentItem)
}
}
return items
},
getPageByName(name){
if (this.$parent.pages && this.$parent.pages.length > 0){
let page = this.$parent.pages.find((p) => {
return p.$attrs.name == name
})
return page
}
return null
},
},
}
</script>
В любом файле используем конструкцию
<template>
<pages style="height : 100%">
<vue-element-loading :active="loading" spinner="bar-fade-scale"/>
<page name="index" title='Список проектов'>
<template slot="toolbar">
<v-btn color="primary" small dark class="mb-2" @click.native="newProject">Новый проект</v-btn>
</template>
<v-data-table
:headers="headers"
:items="projects"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props" :disabled="true">
<td>{{ props.item.name }}</td>
<td class="justify-center layout px-0">
<v-btn flat icon small @click="editItem(props.item)">
<v-icon
small
>
edit
</v-icon>
</v-btn>
<v-btn flat icon small color="error"
@click="deleteItem(props.item)"
:loading="props.item.loading"
>
<v-icon small>
delete
</v-icon>
</v-btn>
</td>
</template>
</v-data-table>
</page>
<page parent="index" name="edit" title='Редактирование'>
<v-form v-model="valid">
<v-layout wrap>
<v-flex xs12>
<v-text-field name="name" :error-messages="errors.collect('name')" :rules="nameRules" required v-model="editedItem.name" label="Название"></v-text-field>
</v-flex>
<v-flex xs12>
<v-spacer></v-spacer>
</v-flex>
</v-layout>
</v-form>
<template slot="actions">
<v-btn small @click.native="close">Отмена</v-btn>
<v-btn
small
:disabled="!valid"
:loading="waitSave"
@click.native="save"
>
Сохранить
</v-btn>
</template>
</page>
</pages>
</template>
Можно осуществить хлебные крошки любого уровня за счет цепочки
parent ссылок в компоненте
page