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