vue.js v-list-group子组不会根据组属性中定义的路径打开

4ioopgfo  于 2023-03-31  发布在  Vue.js
关注(0)|答案(2)|浏览(205)

我有一个嵌套v-list-groups的导航边栏,根据文档,v-list-group的“group”属性将根据路由名称空间扩展组。
参见:https://vuetifyjs.com/en/components/lists/
这与顶级的v-list-group配合得很好。
如果我重新加载页面并且路线与“组”属性匹配,它就会打开。
它不适用于子组v-list-groups。当我重新加载页面时,我可以看到子组正在关闭,所以我认为组 prop 正在工作。但某些东西使它立即关闭。
我的代码有点复杂,我不得不原谅我的变量命名。我呈现了一个导航项列表,如果它们没有定义子组,它将呈现为常规项。如果它们有子组,它将呈现子组。这是两个级别。
这样我就可以在一个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>

如果路由名称空间与组和子组都匹配,则只会打开组,vuetify文档站点对此有一个有效的实现,如果你到那里向下导航到一个子组并刷新页面,子组就会打开。

lx0bsm1f

lx0bsm1f1#

哇!这比我最初预期的要困难得多。我通过直接查看source code for the Vuetify docs website解决了这个问题,特别是main nav drawer componentbase-group componentbase-subgroup componentbase-item component。为了便于组合和维护,这些组件被分离到单独的文件中,但我在下面的模板中重新组合了它们:

<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>

你可能已经注意到了,菜单是从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',
              },
            },
          ]
        },
      ]
    },
  ]
})

Here's a full, working example on codepen。我将其配置为具有/restaurants/japanese/late-night-ramen的起始路由,当您单击任何端点时,应用程序将被路由到的路径将记录在控制台中。希望这对您有帮助!

w6lpcovy

w6lpcovy2#

另一种方法是使用“to”作为路由,此键将自动检测当前路由。

<v-list v-model:opened="open">
      <template v-for="(menu, j) in mainMenu">
        <v-list-group :value="menu.title" >
          <template v-slot:activator="{ props }">
            <v-list-item
              v-bind="props"
              :key="menu.title + j"
              :value="menu.title + j"
            >
              <v-icon>{{ menu.icon }}</v-icon>
              {{ $t(menu.title) }}
            </v-list-item>
          </template>

          <v-list-item
            dense
            v-for="(item, i) in menu.subMenu"
            :key="item.title + j + i"
            :value="item.title + j + i"
            :title="item.title"
            :to="item.path"
          >
          </v-list-item>
        </v-list-group>
      </template>
    </v-list>

相关问题