Как использовать вкладки Vuetify с vue-router

У меня есть следующий jsfiddle, который имеет две вкладки Vuetify. В документации нет примеров использования vue-router с ними.

Я нашел это сообщение Medium.com о том, как использовать Vuetify с vue-router, который имеет следующий код:

<div id="app">
  <v-tabs grow light>
    <v-tabs-bar>
      <v-tabs-item href="/" router>
        <v-icon>motorcycle</v-icon>
      </v-tabs-item>
      <v-tabs-item href="/dog" router>
        <v-icon>pets</v-icon>
      </v-tabs-item>
    </v-tabs-bar>
  </v-tabs>

  <router-view />
</div>

Тем не менее, код устарел, поскольку документация Vuetify 1.0.13 Tabs не указывает опору router в их api, поэтому встроенный пример в сообщении не работает.

Я также нашел этот qaru.site/info/2435971/... который имел следующий код:

<v-tabs-item :to="{path:'/path/to/somewhere'}">

Тем не менее, используя to проп не работает, и он также не указан в апи Vuetify. В отличии от этого, v-button Vuetify компонент делает перечислит to подпирать и использует vue-router, так что я бы ожидать vue-router поддерживал компонент для поддержки, to поддержать.

Копаясь в старых старых документах Vuetify 0.17, to prop указывается для v-tabs-item. Кажется, что поддержка могла быть удалена в 1.0.13.

Как я могу использовать vue-router с вкладками Vuetify?

Ответы

Ответ 1

Обновить

Святой вау! Я попросил сообщество Vuetify добавить документацию к их API, и, похоже, они просто добавили to подпирать, а также другой vue-router реквизит к закладкам документам Vuetify. Серьезно, сообщество там потрясающее.

Оригинальный ответ

Люди в сообществе Vuetify Discord смогли мне помочь. У моего обновленного jsfiddle теперь есть рабочий код.

По существу, v-tab является оболочкой для router-link, где я предполагаю, он использует слоты для передачи реквизита к router-link, поэтому поставив to опору на v-tab работает отлично.

Следующий код - пример рабочего кода:

HTML

<v-app dark>
  <v-tabs fixed-tabs>
    <v-tab to="/foo">Foo</v-tab>
    <v-tab to="/bar">Bar</v-tab>
  </v-tabs>
  <router-view></router-view>
</v-app>

JS

const Foo = {
  template: '<div>Foo component!</div>'
};

const Bar = {
  template: '<div>Bar component!</div>'
};

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
];

const router = new VueRouter({ routes });

new Vue({
  el: '#app',
  router,
});

Результат

Foo tab example Bar tab example

Ответ 2

Я просто добавляю некоторые связанные с анимацией советы и разъясняю использование элементов v-tab-items vs v-tab-item.

Если вы заметили, что использование рабочей разметки, как показано ниже, предотвращает работу анимации переключателей вкладки v-tabs:

<v-tabs v-model="activeTab">
  <v-tab key="tab-1" to="/tab-url-1">tab 1</v-tab>
  <v-tab key="tab-2" to="/tab-url-2">tab 2</v-tab>
</v-tabs>
<router-view />

Если вы хотите сохранить анимацию переключателя табуляции, это способ сделать это.

<v-tabs v-model="activeTab">
  <v-tab key="tab-1" to="/tab-url-1" ripple>
    tab 1
  </v-tab>
  <v-tab key="tab-2" to="/tab-url-2" ripple>
    tab 2
  </v-tab>

  <v-tab-item id="/tab-url-1">
    <router-view v-if="activeTab === '/tab-url-1'" />
  </v-tab-item>
  <v-tab-item id="/tab-url-2">
    <router-view v-if="activeTab === '/tab-url-2'" />
  </v-tab-item>
</v-tabs>

Обратите внимание, что вы можете также использовать v-for циклы на вашей v-tab и v-tab-item метке до тех пор, как ваш, to значение найдено среди id атрибута вашей v-tab-item s.

Если вам нужно разместить содержимое вкладки в другом месте, кроме кнопок вкладок, для этого нужны v-tab-items. Вы можете поместить v-tab-item v-tab-items тег v-tab-items вне компонента v-tabs. Убедитесь, что вы v-model="activeTab" атрибут v-model="activeTab".

Ответ 3

Часть шаблона:

<div>
    <v-tabs
      class="tabs"
      centered
      grow
      height="60px"
      v-model="activeTab"
    >
      <v-tab v-for="tab in tabs" :key="tab.id" :to="tab.route" exact>
        {{ tab.name }}
      </v-tab>
    </v-tabs>
    <router-view></router-view>
</div>

И часть JS:

  data() {
    return {
      activeTab: '/user/${this.id}',
      tabs: [
        { id: 1, name: "Task", route: '/user/${this.id}' },
        { id: 2, name: "Project", route: '/user/${this.id}/project' }
      ]
    };
  }

Маршруты:

{
  path: "/user/:id",
  component: User1,
  props: true,
  children: [
    {
      path: "", //selected tab by default
      component: TaskTab
    },
    {
      path: "project",
      component: ProjectTab
    }
  ]
}

Смотрите пример CodeSanbox

Ответ 4

Ответы @roli-roli и @antoni точны, но в них отсутствуют мелкие детали. Фактически, при использовании их методов (почти эквивалентных) существует проблема в мобильных представлениях; фактически в таких условиях вкладки становятся перелистываемыми. Проблема в том, что при смахивании не будет обновлен маршрут, как ожидалось, при переходе от вкладки A с компонентом A к вкладке B с компонентом B; вместо этого будет activeTab анимация, и activeTab изменится, но маршрутизатор не activeTab.

TL; DR При перелистывании v-tab-item маршрутизатор не обновляется, и вы получаете один и тот же компонент под каждой вкладкой.

Решения могут быть либо отключить возможность прокручивания элемента v-tab-item либо прослушать событие изменения компонента tab чтобы соответствующим образом обновить маршрутизатор. Я бы посоветовал это второе решение (так как в некоторых условиях перелистывание результатов довольно удобно) , но я думаю, что при нажатии на ярлык вкладки это приведет к двойному обновлению маршрутизатора.

Вот рабочий пример на основе ответа @roli-roli

шаблон

<template>
    <v-tabs v-model="activeTab">
        <v-tab v-for="tab in tabs" :key="tab.id" :to="tab.route">{{ tab.name }}</v-tab>

        <v-tabs-items v-model="activeTab" @change="updateRouter($event)">
            <v-tab-item v-for="tab in tabs" :key="tab.id" :to="tab.route">
                <router-view />          
            </v-tab-item>
        </v-tabs-items>
    </v-tabs>
</template>

скрипт

export default {
    data: () => ({
        activeTab: '',
        tabs: [
            {id: '1', name: 'Tab A', route: 'component-a'},
            {id: '2', name: 'Tab B', route: 'component-b'}
        ]
    }),
    methods: {
        updateRouter(val){
            this.$router.push(val)
        }
    }
}

маршрутизатор

Настройте как в предыдущих ответах.

Ответ 5

Следующий код работает для меня

  <v-tabs fixed-tabs>
          <v-tab>Locations</v-tab>
          <v-tab>Employees</v-tab>
          <v-tab-item>Tab 1 content
            <locations-data/>
          </v-tab-item>
          <v-tab-item>Tab 2 content
            <employees-data/>
          </v-tab-item>
    </v-tabs>
   <script>
        import LocationsData from './Settings/Locations';
        import EmployeesData from './Settings/Employees';
        export default {
           components: {
            LocationsData,
            EmployeesData
          },
        }
   </script>