82 votes

Comment utiliser les onglets Vuetify avec vue-router ?

J'ai les éléments suivants jsfiddle qui comporte deux onglets Vuetify. La documentation ne montre pas d'exemples d'utilisation de vue-router avec eux.

J'ai trouvé ceci Article de Medium.com sur la façon d'utiliser Vuetify avec vue-router qui a le code suivant :

<div id="app">
  <v-tabs grow light>
    <v-tabs-bar>
      <v-tabs-item href="http://stackoverflow.com/" router>
        <v-icon>motorcycle</v-icon>
      </v-tabs-item>
      <v-tabs-item href="http://stackoverflow.com/dog" router>
        <v-icon>pets</v-icon>
      </v-tabs-item>
    </v-tabs-bar>
  </v-tabs>

  <router-view />
</div>

Toutefois, ce code est désormais dépassé car le Vuetify 1.0.13 Documentation sur les onglets ne spécifie pas un router dans leur api, donc l'exemple intégré dans le post ne fonctionne pas.

J'ai aussi trouvé ceci Réponse de StackOverflow qui contenait le code suivant :

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

Cependant, l'utilisation de la to prop ne fonctionne pas et n'est pas non plus répertorié dans l'api Vuetify. En revanche, la v-button Le composant Vuetify contient un to prop et utilise vue-router donc je m'attendrais à un vue-router pour soutenir le to prop.

Fouiller dans le vieux ancienne documentation de Vuetify 0.17 le to est spécifié pour v-tabs-item . Il semble que cette prise en charge ait été supprimée dans la version 1.0.13.

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

98voto

homersimpson Points 988

Mise à jour

Bon sang de bonsoir ! J'ai demandé à la communauté Vuetify d'ajouter de la documentation à leur api, et il semble qu'ils viennent d'ajouter l'option to ainsi que d'autres vue-router props à la Documentation sur les onglets Vuetify . Sérieusement, la communauté est géniale.

Réponse originale

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

Essentiellement, v-tab est une enveloppe pour router-link où je suppose qu'il utilise des slots pour passer des props à router-link donc en mettant 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 example Bar tab example

0 votes

Merci pour cela ! J'ai créé un fork de votre fiddle mis à jour pour ajouter une route par défaut à l'onglet si quelqu'un est intéressé : jsfiddle.net/thorne51/9g2zeow1/2

0 votes

Que faire si l'on veut passer des props au composant ?

1 votes

Le problème est de faire fonctionner l'animation entre les routes...

28voto

roli roli Points 2157

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

0 votes

Le problème que je vois, c'est qu'en essayant de faire cela, il finit par charger chaque page deux fois. Si vous regardez pour mounted() vous verrez que la page est chargée deux fois lorsque vous utilisez des onglets pour le routage. Il faut trouver une solution à ce problème. codesandbox.io/s/vuetify-v-tabs-with-vue-router-in1le regarder la console pour "build loaded" ne devrait le faire qu'une seule fois, mais en fait il monte deux fois.

0 votes

J'ai trouvé. J'ai remarqué que c'est la boucle route-view que tu utilises. Tu ne devrais pas lancer le route-view dans le tableau des onglets. Ca le fait charger deux fois.

2 votes

@timothymarois vous avez tout à fait raison. J'ai mis à jour ma réponse et maintenant cela devrait fonctionner comme prévu.

17voto

antoni Points 1889

J'ajoute simplement quelques conseils relatifs à l'animation et je clarifie l'utilisation de l'option v-tab-items vs v-tab-item .

Si vous avez remarqué, l'utilisation de la balise de travail suivante empêche l'animation de changement d'onglet v-tabs de fonctionner :

<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 du changement 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 un v-for boucle sur votre v-tab y v-tab-item tant que votre to est trouvé parmi les id de votre v-tab-item s.

Si vous devez placer le contenu de vos onglets à un endroit différent de celui de vos boutons d'onglets, voici ce qu'il faut faire. v-tab-items est pour. Vous pouvez placer le v-tab-item dans un v-tab-items en dehors de la balise v-tabs composant. Assurez-vous de lui donner un v-model="activeTab" attribut.

2voto

Gabriel Rambaud Points 45

Les réponses de @roli-roli et @antoni sont correctes mais il manque un petit détail. En fait, en utilisant leurs méthodes (presque équivalentes), il y a un problème dans les vues mobiles ; en effet, dans ces conditions, les onglets deviennent glissants. Le problème est que le glissement ne met pas à jour la route comme prévu, en 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 l'élément activeTab va changer, mais le routeur ne sera pas mis à jour.

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

Les solutions pourraient consister à désactiver la possibilité de glisser le doigt dans les documents v-tab-item ou en écoutant l'événement de changement de l tab pour mettre à jour le routeur en conséquence. Je conseillerais cette deuxième solution (puisque le swiping est très pratique 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 fonctionnel basé sur la réponse de @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>

script

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

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

1 votes

Merci ! Utilisez :value="tab.route" au lieu de :to et <router-view>.

0 votes

@Stevie-RayHartog : oui, j'ai corrigé cette vue de routeur mal écrite. Pourquoi suggérez-vous d'utiliser :value au lieu de :to ?

0 votes

Le problème que je vois est que lorsque j'essaie de faire cela, chaque page est chargée deux fois. Si vous regardez pour mounted() vous verrez qu'il charge la page deux fois lorsqu'il utilise des onglets pour le routage. Il faut trouver une solution à ce problème. codesandbox.io/s/vuetify-v-tabs-with-vue-router-in1le regarder la console pour "build loaded" ne devrait le faire qu'une seule fois, mais en fait il monte deux fois.

-1voto

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>

0 votes

Pour la première fois, j'ai une ligne étirée sous l'onglet pour la première fois, comment résoudre ce problème ?

0 votes

J'ai fait comme vous dans le passé et si je me souviens bien, cela charge chaque sous-composant lorsque le principal est monté. Alors qu'en jouant avec :to o to props chargent le composant correspondant uniquement lorsque l'onglet est cliqué. Ce qui est mieux à mon avis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X