Как использовать вкладки 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,
});
Результат
Ответ 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>