[英]How to use Vuetify tabs with vue-router
I have the following jsfiddle that has two Vuetify tabs.我有以下jsfiddle ,它有两个 Vuetify 选项卡。 The documentation doesn't show examples on using vue-router
with them.该文档没有显示使用vue-router
示例。
I found this Medium.com post on how to use Vuetify with vue-router
, which has the following code:我在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>
However, the code is now outdated as the Vuetify 1.0.13 Tabs documentation doesn't specify a router
prop in their api, so the embedded example in the post doesn't work.但是,代码现在已经过时,因为Vuetify 1.0.13 Tabs 文档没有在他们的 api 中指定router
道具,因此帖子中的嵌入式示例不起作用。
I also found this StackOverflow answer which had the following code:我还发现了这个StackOverflow 答案,其中包含以下代码:
<v-tabs-item :to="{path:'/path/to/somewhere'}">
However, using the to
prop doesn't work and it's also not listed in the Vuetify api.但是,使用to
道具不起作用,并且它也未列在 Vuetify api 中。 In contrast, the v-button
Vuetify component does list a to
prop and utilizes vue-router
, so I would expect a vue-router
supported component to support the to
prop.相比之下, v-button
Vuetify 组件确实列出了一个to
prop 并使用了vue-router
,所以我希望vue-router
支持的组件支持to
prop。
Digging around in the old old Vuetify 0.17 docs , the to
prop is specified for v-tabs-item
.在旧的 Vuetify 0.17 文档中挖掘,为v-tabs-item
指定了to
道具。 It seems that support might have been removed in 1.0.13.似乎支持可能已在 1.0.13 中删除。
How can I use vue-router
with Vuetify tabs?如何将vue-router
与 Vuetify 选项卡一起使用?
Holy wow!圣哇! I asked the Vuetify community to add documentation to their api, and it looks like they just added the to
prop as well as other vue-router
props to the Vuetify tabs docs .我要求 Vuetify 社区向他们的 api 添加文档,看起来他们只是将to
prop 以及其他vue-router
props 添加到Vuetify tabs docs 。 Seriously, the community there is awesome.说真的,那里的社区很棒。
The folks in the Vuetify community Discord were able to help me out. Vuetify 社区 Discord 中的人能够帮助我。 My updated jsfiddle now has the working code.我更新的jsfiddle现在有工作代码。
Essentially, v-tab
is a wrapper for router-link
, where I assume it uses slots to pass props to router-link
, so putting the to
prop on v-tab
works fine.本质上, v-tab
是router-link
的包装器,我假设它使用插槽将道具传递给router-link
,因此将to
prop 放在v-tab
效果很好。
The following code is an example of the working code:以下代码是工作代码的示例:
<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>
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,
});
The template part:模板部分:
<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>
And the js part:和 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` }
]
};
}
Routes:路线:
{
path: "/user/:id",
component: User1,
props: true,
children: [
{
path: "", //selected tab by default
component: TaskTab
},
{
path: "project",
component: ProjectTab
}
]
}
I'm just adding some animation-related tips here & clarifying the use of v-tab-items
vs v-tab-item
.我只是在这里添加了一些与动画相关的技巧,并阐明了v-tab-items
与v-tab-item
。
If you have noticed, using the working markup as follows prevents the v-tabs tab switch animation to work:如果您已经注意到,使用如下工作标记会阻止 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 />
If you want to keep the tab switch animation, this is a way to do it.如果您想保留选项卡切换动画,这是一种方法。
<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>
Note that you can also use a
v-for
loop on yourv-tab
andv-tab-item
tags as long as yourto
value is found among theid
attribute of yourv-tab-item
s.请注意,您也可以在v-tab
和v-tab-item
标签上使用v-for
循环,只要在v-tab-item
的id
属性中找到to
值即可。If you need to place your tab contents in a different place than your tabs buttons, this is what
v-tab-items
is for.如果您需要将标签内容放置在与标签按钮不同的位置,这就是v-tab-items
的用途。 You can place thev-tab-item
s in av-tab-items
tag outside of thev-tabs
component.您可以将v-tab-item
放在v-tabs
组件外部的v-tab-items
标签中。 Make sure you give it av-model="activeTab"
attribute.确保给它一个v-model="activeTab"
属性。
The answers of @roli-roli and @antoni are currect but lacking of a tiny detail. @roli-roli 和@antoni 的答案是正确的,但缺乏细节。 In fact, using their methods (almost equivalent) there is an issue in mobile views;事实上,使用他们的方法(几乎等价)在移动视图中存在问题; in fact, in such conditions tabs become swipeable.事实上,在这种情况下,标签变得可滑动。 The problem is that swiping won't update the route as expected, passing from Tab A with component A to Tab B with component B;问题是滑动不会按预期更新路由,从带有组件 A 的 Tab A 传递到带有组件 B 的 Tab B; instead, an animation will be fired and the activeTab
will change, but the router won't update.相反,将触发动画并且activeTab
将更改,但路由器不会更新。
TL;DR Swiping the v-tab-item
does not update the router, and you get the same component under each tab. TL;DR 滑动v-tab-item
不会更新路由器,您会在每个选项卡下获得相同的组件。
Solutions could be either disable the swipeability of v-tab-item
or listening to the change event of the tab
component to update the router accordingly.解决方案可以是禁用v-tab-item
的可滑动性或监听tab
组件的更改事件以相应地更新路由器。 I would advise this second solution (since swiping results pretty handy in some conditions)
, but I thik that this would trigger twice the router update when clicking on the tab's label.
我会建议第二个解决方案(因为在某些情况下刷卡结果非常方便)
,但我认为这会在单击选项卡标签时触发两次路由器更新。
<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)
}
}
}
Set up as in previous answers.按照之前的答案进行设置。
//urls in some componet
<v-btn @click="goToUrl({name: 'RouteName1'})">
.....
<v-list-item-title
@click="goToUrl({name: 'RouteName2'})"
>
Some tab link text
</v-list-item-title>
....
//tabs menu and content in other component
<v-tabs>
<v-tab key="key_name1" :to="{ name: 'RouteName1'}">Some link 1</v-tab>
<v-tab key="key_name2" :to="{ name: 'RouteName2'}">Some link 2</v-tab>
<v-tab-item key="key_name1" value="/url/for/route1">
....
<v-tab-item key="key_name2" value="/url/for/route2">
....
I just want to add a fix for double mounting of the new component when a tab is switched to.我只想在切换到选项卡时为新组件的双重安装添加修复程序。 You can see the question and answer here .您可以在此处查看问题和答案。
The TLDR is that if you use a v-for within the , you are going to run into a problem where the component you are switching to will be created, destroyed and then created again on each switch. TLDR 是,如果您在 中使用 v-for,您将遇到一个问题,即您要切换到的组件将被创建、销毁,然后在每次切换时再次创建。 If, like me, you do an ajax call on the create side of that, then you will be hitting your back end twice for every tab switch.如果像我一样,您在创建端执行 ajax 调用,那么您将在每次选项卡切换时点击后端两次。 You can wrap the with a to prevent that.你可以用 a 包裹来防止这种情况。
in the answer I go into depth about why this happens.在回答中,我深入探讨了为什么会发生这种情况。
The following code works for me以下代码对我有用
<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>
And keep your existing query params: usefull eg if you have a :locale in your url:并保留您现有的查询参数:有用,例如,如果您的网址中有 :locale:
<v-tabs v-model="activeTab">
<v-tab v-for="tab in tabs" :key="tab.id" :to="tab.to">
{{ tab.name }}
</v-tab>
</v-tabs>
<v-tabs-items v-model="activeTab" @change="updateRouter($event)">
<v-tab-item v-for="tab in tabs" :key="tab.id" :value="tab.to">
<router-view />
</v-tab-item>
</v-tabs-items>
export default {
data: () => ({
activeTab: '',
}),
computed: {
tabs() {
return [
{ id: 1, name: 'Tab one', to: this.getTabPath('routeName1') },
{ id: 2, name: 'Tab two', to: this.getTabPath('routeName2') },
{ id: 3, name: 'Tab three', to: this.getTabPath('routeName3') },
{ id: 4, name: 'Tab four', to: this.getTabPath('routeName4') },
]
},
},
methods: {
getTabPath(name) {
// Get the path without losing params. Usefull e.g. if you have a :locale in your url:
return this.$router.resolve({ name, params: this.$route.params }).href
},
updateRouter(path) {
// Gets called upon swipe.
this.$router.push(path)
},
},
}
Using $router.resolve
to get the path from a route object as explained here .使用$router.resolve
作为解释得到的路由对象的路径在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.