web-dev-qa-db-fra.com

Comment utiliser les onglets Vuetify avec vue-router

J'ai le suivant jsfiddle qui a deux onglets Vuetify. La documentation ne montre pas d'exemples d'utilisation de vue-router avec eux.

J'ai trouvé ceci message sur Medium.com sur l'utilisation de Vuetify avec vue-router, qui a le code suivant:

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

Cependant, le code est maintenant obsolète, car la documentation de Vuetify 1.0.13 Tabs ne spécifie pas un prop de router dans son api, de sorte que l'exemple incorporé dans l'article ne fonctionne pas.

J'ai aussi trouvé ceci réponse StackOverflow qui avait le code suivant:

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

Cependant, l'utilisation de to prop ne fonctionne pas et n'est pas répertoriée dans l'API Vuetify. En revanche, le v-button Le composant Vuetify répertorie un to prop et utilise vue-router, donc je m'attendrais à un vue-router _ composant supporté pour supporter le to prop.

En fouillant dans l’ancien ancien Vuetify 0.17 docs , le to prop est spécifié pour v-tabs-item. Il semble que le support ait peut-être été supprimé dans 1.0.13.

Comment puis-je utiliser vue-router avec les onglets Vuetify?

35
homersimpson

Mise à jour

Saint wow! J'ai demandé à la communauté Vuetify d'ajouter de la documentation à leur API, et il semble qu'ils viennent d'ajouter le to prop ainsi que d'autres vue-router accessoires pour le docs Vuetify . Sérieusement, la communauté est géniale.

Réponse originale

Les membres de la communauté Vuetify Discord ont pu m'aider. Mon mis à jour jsfiddle a maintenant le code de travail.

Essentiellement, v-tab est un wrapper pour router-link, où je suppose qu’il utilise des machines à sous pour transmettre des accessoires à router-link, mettant ainsi le to prop sur v-tab fonctionne bien.

Le code suivant est un exemple du code de travail:

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,
});

Résultat

Foo tab exampleBar tab example

37
homersimpson

J'ajoute ici quelques astuces relatives à l'animation et clarifie l'utilisation de v-tab-items Vs v-tab-item.

Si vous avez remarqué, l’utilisation du balisage de travail comme suit empêche l’animation de basculement de l’onglet 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 />

Si vous souhaitez conserver l’animation de commutateur d’onglet, c’est une façon de le faire.

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

Notez que vous pouvez également utiliser une boucle v-for Sur vos balises v-tab Et v-tab-item Tant que votre valeur to est trouvée parmi les id attribut de votre v-tab-item s.

Si vous avez besoin de placer le contenu de vos onglets à un endroit différent de celui de leurs boutons, voici à quoi sert v-tab-items. Vous pouvez placer le v-tab-item Dans une balise v-tab-items En dehors du composant v-tabs. Assurez-vous de lui attribuer un attribut v-model="activeTab".

10
antoni

La partie modèle:

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

Et la partie 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` }
      ]
    };
  }

Itinéraires:

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

voir l'exemple de codesanbox

9
roli roli

Les réponses de @ roli-roli et @antoni sont exactes mais manquent d'un détail infime. En fait, en utilisant leurs méthodes (presque équivalentes), il existe un problème dans les vues mobiles; En fait, dans de telles conditions, les onglets deviennent insérables. Le problème est que le balayage ne mettra pas à jour la route comme prévu, passant de l'onglet A avec le composant A à l'onglet B avec le composant B; au lieu de cela, une animation sera déclenchée et le activeTab changera, mais le routeur ne se mettra pas à jour.

TL; DR Balayer le v-tab-item ne met pas à jour le routeur et vous obtenez le même composant sous chaque onglet.

Les solutions pourraient être soit de désactiver la possibilité de glisser de v-tab-item ou l'écoute de l'événement change du composant tab pour mettre à jour le routeur en conséquence. Je conseillerais cette deuxième solution (car les résultats sont plutôt pratiques dans certaines conditions), mais je pense que cela déclencherait deux fois la mise à jour du routeur en cliquant sur l'étiquette de l'onglet.

Voici un exemple de travail basé sur la réponse @ roli-roli

Modèle

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

Scénario

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

Routeur

Mettre en place comme dans les réponses précédentes.

3
Gabriel Rambaud

Le code suivant fonctionne pour moi

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