繁体   English   中英

如何在 vue-router 中使用 Vuetify 选项卡

[英]How to use Vuetify tabs with 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 文档没有在他们的 api 中指定router道具,因此帖子中的嵌入式示例不起作用。

我还发现了这个StackOverflow 答案,其中包含以下代码:

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

但是,使用to道具不起作用,并且它也未列在 Vuetify api 中。 相比之下, v-button Vuetify 组件确实列出了一个to prop 并使用了vue-router ,所以我希望vue-router支持的组件支持to prop。

旧的 Vuetify 0.17 文档中挖掘,为v-tabs-item指定了to道具。 似乎支持可能已在 1.0.13 中删除。

如何将vue-router与 Vuetify 选项卡一起使用?

更新

圣哇! 我要求 Vuetify 社区向他们的 api 添加文档,看起来他们只是将to prop 以及其他vue-router props 添加到Vuetify tabs docs 说真的,那里的社区很棒。

原答案

Vuetify 社区 Discord 中的人能够帮助我。 我更新的jsfiddle现在有工作代码。

本质上, v-tabrouter-link的包装器,我假设它使用插槽将道具传递给router-link ,因此将to prop 放在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 选项卡示例 条形标签示例

模板部分:

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

我只是在这里添加了一些与动画相关的技巧,并阐明了v-tab-itemsv-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-tabv-tab-item标签上使用v-for循环,只要在v-tab-itemid属性中找到to值即可。

如果您需要将标签内容放置在与标签按钮不同的位置,这就是v-tab-items的用途。 您可以将v-tab-item放在v-tabs组件外部的v-tab-items标签中。 确保给它一个v-model="activeTab"属性。

@roli-roli 和@antoni 的答案是正确的,但缺乏细节。 事实上,使用他们的方法(几乎等价)在移动视图中存在问题; 事实上,在这种情况下,标签变得可滑动。 问题是滑动不会按预期更新路由,从带有组件 A 的 Tab A 传递到带有组件 B 的 Tab B; 相反,将触发动画并且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)
        }
    }
}

路由器

按照之前的答案进行设置。

//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">
    ....

我只想在切换到选项卡时为新组件的双重安装添加修复程序。 您可以在此处查看问题和答案。

TLDR 是,如果您在 中使用 v-for,您将遇到一个问题,即您要切换到的组件将被创建、销毁,然后在每次切换时再次创建。 如果像我一样,您在创建端执行 ajax 调用,那么您将在每次选项卡切换时点击后端两次。 你可以用 a 包裹来防止这种情况。

在回答中,我深入探讨了为什么会发生这种情况。

以下代码对我有用

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

启用动画和滑动

并保留您现有的查询参数:有用,例如,如果您的网址中有 :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)
    },
  },
}

使用$router.resolve作为解释得到的路由对象的路径在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM