Tho*_*ear 2 javascript vue.js vuetify.js
我有一个带有嵌套 v-list-groups 的导航侧边栏。根据文档, v-list-group 的“group”属性将根据路由命名空间扩展组。
请参阅: https: //vuetifyjs.com/en/components/lists/
这与顶级 v-list-group 配合得很好。
如果我重新加载页面并且路线与“group”属性匹配,它将打开。
它不适用于子组 v-list-groups。当我重新加载页面时,我可以看到子组关闭,所以我认为组道具正在工作。但有什么东西让它立即关闭。
我的代码有点复杂,我必须原谅我的变量命名。我正在渲染导航项目列表,如果它们没有定义子组,它将呈现为常规项目。如果它们有子组,则会呈现子组。这降低了两个级别。
这样我就可以在单个 json 文件中定义整个导航栏并导入它。
<template>
<v-list dense nav>
<template v-for="(sidebarItem, sidebarIndex) in sidebarItems">
<v-list-item
v-if="arrayIsEmptyOrUndefined(sidebarItem.subGroup)"
:key="sidebarIndex"
:to="sidebarItem.linkTo"
nuxt
>
<v-list-item-action>
<v-icon>{{ sidebarItem.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="sidebarItem.title" />
</v-list-item-content>
</v-list-item>
<v-list-group
v-if="
(!arrayIsEmptyOrUndefined(sidebarItem.subGroup) &&
typeof sidebarItem.subGroup !== 'undefined')
"
:key="sidebarIndex"
:prepend-icon="sidebarItem.icon"
:group="sidebarItem.linkTo"
>
<template v-slot:activator>
<v-list-item-content>
<v-list-item-title>{{ sidebarItem.title }}</v-list-item-title>
</v-list-item-content>
</template>
<v-list-item
v-if="arrayIsEmptyOrUndefined(sidebarItem.subGroup)"
:key="subGroupIndex"
:to="sidebarItem.linkTo"
nuxt
>
<v-list-item-action>
<v-icon>{{ sidebarItem.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="sidebarItem.title" />
</v-list-item-content>
</v-list-item>
<template v-for="(subGroupItem, subGroupIndex) in sidebarItem.subGroup">
<v-list-item
v-if="arrayIsEmptyOrUndefined(subGroupItem.subGroup)"
:key="subGroupIndex"
:to="subGroupItem.linkTo"
nuxt
>
<v-list-item-action>
<v-icon>{{ subGroupItem.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="subGroupItem.title" />
</v-list-item-content>
</v-list-item>
<v-list-group
v-if="
(!arrayIsEmptyOrUndefined(subGroupItem.subGroup) &&
typeof subGroupItem.subGroup !== 'undefined')
"
:key="subGroupIndex"
sub-group
:group="subGroupItem.linkTo"
>
<template v-slot:activator>
<v-list-item-content>
<v-list-item-title>{{ subGroupItem.title }}</v-list-item-title>
</v-list-item-content>
</template>
<v-list-item
v-for="(subGroupSubGroupItem, subGroupSubGroupIndex) in subGroupItem.subGroup"
:key="subGroupSubGroupIndex"
:to="subGroupSubGroupItem.linkTo"
nuxt
exact
>
<v-list-item-content>
<v-list-item-title v-text="subGroupSubGroupItem.title" />
</v-list-item-content>
<v-list-item-action>
<v-icon>{{ subGroupSubGroupItem.icon }}</v-icon>
</v-list-item-action>
</v-list-item>
</v-list-group>
</template>
</v-list-group>
</template>
</v-list>
</template>
Run Code Online (Sandbox Code Playgroud)
如果路由命名空间同时匹配组和子组,则仅打开组。vuetify 文档网站有一个有效的实现。如果您去那里并向下导航到子组并刷新页面。该小组将开放。
哇!这最终比我最初预期的要困难。我通过直接查看Vuetify 文档网站的源代码解决了这个问题,特别是主导航抽屉组件、base-group组件、base-subgroup组件和base-item组件。为了便于组合和维护,这些组件被分成单独的文件,但我在下面的模板中重新组合了它们:
<template>
<v-navigation-drawer permanent>
<v-toolbar color="indigo" dark>
<v-app-bar-nav-icon></v-app-bar-nav-icon>
<v-toolbar-title>Main Menu</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</v-toolbar>
<v-list
dense
expand
nav
>
<!-- ENTIRE list is wrapped in a template -->
<template v-for="item in $router.options.routes">
<!-- use v-if to determine if 2nd level nesting is needed -->
<!-- if it's a menu item with no children -->
<v-list-item
v-if="!item.children"
color="indigo"
:key="item.name`"
:to="item.path"
>
<v-list-item-icon>
<v-icon>{{ `mdi-${item.meta.icon}` }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ item.name }}</v-list-item-title>
</v-list-item>
<!-- else if it has children -->
<v-list-group
v-else
:group="item.path"
color="indigo"
>
<!-- this template is for the title of top-level items with children -->
<template #activator>
<v-list-item-content>
<v-list-item-title>
<v-icon>{{ `mdi-${item.meta.icon}` }}</v-icon>
{{ item.name }}
</v-list-item-title>
</v-list-item-content>
</template>
<!-- this template is for the children/sub-items (2nd level) -->
<template v-for="subItem in item.children">
<!-- another v-if to determine if there's a 3rd level -->
<!-- if there is NOT a 3rd level -->
<v-list-item
v-if="!subItem.children"
class="ml-5"
:key="subItem.name"
:to="item.path + subItem.path"
>
<v-list-item-icon class="mr-4">
<v-icon v-text="`mdi-${subItem.meta.icon}`" />
</v-list-item-icon>
<v-list-item-title class="ml-0">
{{ subItem.name }}
</v-list-item-title>
</v-list-item>
<!-- if there is a 3rd level -->
<v-list-group
v-else
color="indigo"
:group="subItem.path"
sub-group
>
<template #activator>
<v-list-item-content>
<v-list-item-title>
<v-icon>{{ `mdi-${subItem.meta.icon}` }}</v-icon>
{{ subItem.name }}
</v-list-item-title>
</v-list-item-content>
</template>
<template v-for="(subSubItem, k) in subItem.children">
<v-list-item
:key="`subheader-${k}`"
color="indigo"
:value="true"
:to="item.path + subItem.path + subSubItem.path"
>
<v-list-item-title>{{ subSubItem.name }}</v-list-item-title>
<v-list-item-icon>
<v-icon>{{ `mdi-${subSubItem.meta.icon}` }}</v-icon>
</v-list-item-icon>
</v-list-item>
</template>
</v-list-group>
</template>
</v-list-group>
</template>
</v-list>
</v-navigation-drawer>
</template>
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到,菜单是根据 Vue Router 中的路由列表生成的。路由器定义如下所示(注意:因为这只是一个示例,所以我没有将组件与每个路由关联起来,但实际上,这是必要的):
const router = new VueRouter({
routes: [
{
name: 'No Children (1 level)',
path: '/no-children',
meta: {
icon: 'baby-carriage-off',
},
},
{
name: 'Attractions (2 levels)',
path: '/attractions',
meta: {
icon: 'airballoon',
},
children: [
{
name: 'Carnivals',
path: '/carnivals',
meta: {
icon: 'drama-masks',
},
},
{
name: 'Museums',
path: '/museums',
meta: {
icon: 'bank',
},
},
]
},
{
name: 'Restaurants (3 levels)',
path: '/restaurants',
meta: {
icon: 'silverware-fork-knife',
},
children: [
{
name: 'Japanese',
path: '/japanese',
meta: {
icon: 'map-marker-radius-outline',
},
children: [
{
name: 'Hikari Sushi',
path: '/hikari-sushi',
meta: {
icon: 'food-croissant',
},
},
{
name: 'Late Night Ramen',
path: '/late-night-ramen',
meta: {
icon: 'noodles',
},
},
]
},
{
name: 'Italian',
path: '/italian',
meta: {
icon: 'map',
},
children: [
{
name: 'Jersey Pizza',
path: '/jersey-pizza',
meta: {
icon: 'pizza',
},
},
{
name: 'Im-pasta-ble',
path: '/im-pasta-ble',
meta: {
icon: 'pasta',
},
},
]
},
{
name: 'Mexican',
path: '/mexican',
meta: {
icon: 'map-marker',
},
children: [
{
name: 'Taco Gato',
path: '/taco-gato',
meta: {
icon: 'taco',
},
},
{
name: 'A-maize-ing',
path: '/a-maize-ing',
meta: {
icon: 'corn',
},
},
]
},
]
},
]
})
Run Code Online (Sandbox Code Playgroud)
这是关于 codepen 的完整的、有效的示例。我将其配置为具有起始路由/restaurants/japanese/late-night-ramen,当您单击任何端点时,应用程序将路由到的路径将记录在控制台中。希望这可以帮助!