Vue.js: Comment définir un ID unique pour chaque instance de composant?

115

Je veux créer un composant avec Vue.js contenant une étiquette et une entrée. par exemple :

<label for="inputId">Label text</label>
<input id="inputId" type="text" />

Comment puis-je définir un ID unique pour chaque instance de composant?

Je vous remercie.

PierreB
la source
Il existe plusieurs packages / mixins que vous pouvez consulter: vue-ucid , vue-component-id , vue-uniq-ids .
str le
N'ayant pas vu le commentaire précédent auparavant, j'ai également publié le plugin vue-unique-id Vue pour cela sur npm .
bernie

Réponses:

175

Chaque composant a un identifiant unique auquel on peut accéder en tant que this._uid.

<template>
  <div>
    <label :for="id">Label text for {{id}}</label>
    <input :id="id" type="text" />
  </div>
</template>

<script>
export default {
  data () {
    return {
      id: null
    }
  }, 
  mounted () {
    this.id = this._uid
  }
}
</script>

Si vous voulez plus de contrôle sur les identifiants, vous pouvez par exemple les générer dans un composant parent.

zxzak
la source
Notez que la readyméthode a été supprimée dans Vue 2.0 et au-dessus. J'étais très confus lorsque la readyméthode ne s'exécutait pas. stackoverflow.com/a/40209796/126751
Brendan Wood
1
... et datadoit être une fonction qui renvoie un objet: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
arminrosu
3
Malheureusement, cela ne fonctionne pas dans TypeScript, car ce this._uidn'est pas valide. Au lieu de cela, générez votre identifiant vous-même, par exemple public id = uuid4();, voir uuid4 .
Erik Vullings
2
J'ai dû mettre l'initialisation dans la méthode beforeMount () pour m'assurer que l'identifiant était défini dans le DOM lorsque j'ai essayé d'y accéder à partir de la méthode mount ().
Stéphane Gerber
34

Pour le point de Nihat (ci-dessus): Evan You a déconseillé d'utiliser _uid: "Le vm _uid est réservé à un usage interne et il est important de le garder privé (et de ne pas s'y fier dans le code utilisateur) afin que nous gardions la flexibilité de changer son comportement pour de futurs cas d'utilisation potentiels. ... Je suggérerais de générer vous-même des UID [en utilisant un module, un mixin global, etc.] "

Utiliser le mixin suggéré dans ce problème GitHub pour générer l'UID semble être une meilleure approche:

let uuid = 0;

export default {
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
};
nerprun
la source
un lien vers le problème GitHub pertinent serait très utile ici
Damon
1
Voici le problème GitHub où Evan déconseille d'utiliser _id
jannej
19

Mise à jour: le code générera une erreur si la ._uidpropriété n'existe pas dans l'instance afin que vous puissiez la mettre à jour pour utiliser quelque chose de personnalisé ou une nouvelle propriété d'identifiant unique si elle est fournie par Vue.

Bien que la réponse de zxzak soit excellente; _uidn'est pas une propriété d'API publiée. Pour enregistrer un mal de tête au cas où il changerait à l'avenir, vous pouvez mettre à jour votre code avec un seul changement avec une solution de plugin comme ci-dessous.

Vue.use({
    install: function(Vue, options) {
        Object.defineProperty(Vue.prototype, "uniqId", {
            get: function uniqId() {
                if ('_uid' in this) {
                   return this._uid;
                }
                throw new Error("_uid property does not exist");
            }
        });
    }
});
Nihat
la source
Ceci utilise toujours l'uid, qui dans votre propre réponse reconnaît qu'il est déconseillé. Veuillez ne pas publier de réponses préconisant de mauvaises pratiques. Cette réponse doit être supprimée.
Développement web hybride
2
Oui, mais dans le cas où l'API publiée est modifiée / supprimée, ils ne devront changer qu'un seul endroit dans tout le code. Dans l'autre réponse, c'était par composant. Je l'ai déjà souligné dans le titre.
Nihat
De plus, je viens de mettre à jour le code afin qu'il génère une erreur au cas où la _uidpropriété n'existerait plus.
Nihat
14

Mettre à jour

J'ai publié le plugin vue-unique-id Vue pour cela sur npm .

Répondre

Aucune des autres solutions ne répond à l'exigence d'avoir plus d'un élément de formulaire dans votre composant. Voici mon point de vue sur un plugin qui s'appuie sur des réponses précédemment données:

Vue.use((Vue) => {
  // Assign a unique id to each component
  let uuid = 0;
  Vue.mixin({
    beforeCreate: function() {
      this.uuid = uuid.toString();
      uuid += 1;
    },
  });

  // Generate a component-scoped id
  Vue.prototype.$id = function(id) {
    return "uid-" + this.uuid + "-" + id;
  };
});

Cela ne dépend pas de la _uidpropriété interne qui est réservée à un usage interne .

Utilisez-le comme ceci dans votre composant:

<label :for="$id('field1')">Field 1</label>
<input :id="$id('field1')" type="text" />

<label :for="$id('field2')">Field 2</label>
<input :id="$id('field2')" type="text" />

Pour produire quelque chose comme ça:

<label for="uid-42-field1">Field 1</label>
<input id="uid-42-field1" type="text" />

<label for="uid-42-field2">Field 2</label>
<input id="uid-42-field2" type="text" />
Bernie
la source
3
npm i -S lodash.uniqueid

Puis dans votre code ...

<script>
  const uniqueId = require('lodash.uniqueid')

  export default {
    data () {
      return {
        id: ''
      }
    },
    mounted () {
       this.id = uniqueId()
    }
  }
</script>

De cette façon, vous ne chargez pas l'intégralité de la bibliothèque lodash, ni même enregistrez la bibliothèque entière dans node_modules.

Meconroy
la source
2

Dans Vue2, utilisez v-bind.

Dis que j'ai un objet pour un sondage

  <div class="options" v-for="option in poll.body.options">
    <div class="poll-item">
      <label v-bind:for="option._id" v-bind:style="{color: option.color}">{{option.text}}</label>
      <input type="radio" v-model="picked" v-bind:value="option._id" v-bind:id="option._id">
  </div>
  </div>
趙曉明
la source
Ce que vous devriez rechercher v-for="(option, index) in poll.body.options", c'est et utiliser indexdans votre v-bind.
Warre Buysse
1

Une approche simple que je n'ai pas vue dans les réponses est:

<template>
  <div>
    <label :for="id">Label text for {{id}}</label>
    <input :id="id" type="text" />
  </div>
</template>

<script>
import uniqueId from 'lodash-es/uniqueId'

export default {
  computed: {
    id () {
      # return this._uid
      return uniqueId('id')
    }
  }
}
</script>
Cristi Draghici
la source
1
Le créateur de Vue.js dit que vous devriez éviter d'utiliser _uid car il est à usage interne et un jour, ils peuvent le supprimer, le renommer ou changer son comportement.
Omid Sadeghi
1
Merci, je pense que c'est correct. J'ai mis à jour le code avec une solution différente, j'espère encore assez simple. Quoi qu'il en soit, l'idée de cet exemple était d'utiliser une propriété calculée.
Cristi Draghici
uniqueId de lodash est la meilleure approche à mon avis
Giorgio Tempesta
1

Si vous utilisez TypeScript, sans plugin, vous pouvez simplement ajouter un identifiant statique dans votre composant de classe et l'incrémenter dans la méthode created (). Chaque composant aura un identifiant unique (ajoutez un préfixe de chaîne pour éviter la collision avec d'autres composants qui utilisent le même conseil)

<template>
  <div>
    <label :for="id">Label text for {{id}}</label>
    <input :id="id" type="text" />
  </div>
</template>

<script lang="ts">
  ...
  @Component
  export default class MyComponent extends Vue {
    private id!: string;
    private static componentId = 0;
    ...
    created() {
      MyComponent.componentId += 1;
      this.id = `my-component-${MyComponent.componentId}`;
    }
 </script>
JMess
la source
0

Ce package semble être une bonne solution pour le problème sous-jacent d'avoir des identifiants non uniques dans votre DOM sur plusieurs composants:

vue-uniq-ids

C'est une tendance à utiliser des composants. Les composants sont sympas, ils sont petits, évidents, faciles à utiliser et modulaires. Jusqu'à ce qu'il s'agisse de la propriété id.

Certains attributs de balise HTML nécessitent l'utilisation d'une propriété id, comme label [for], input [form] et de nombreux attributs aria- *. Et le problème avec l'identifiant est qu'il n'est pas modulaire. Si plusieurs propriétés d'identifiant sur la page ont la même valeur, elles peuvent s'influencer mutuellement.

VueUniqIds vous aide à vous débarrasser de ce problème. Il fournit l'ensemble des directives liées à l'id dont la valeur est automatiquement modifiée en ajoutant une chaîne unique tout en gardant l'attrbitue facile à lire.

essayer
la source
-4

Si votre uid n'est pas utilisé par un autre composant, j'ai une idée.

uid: Math.random()

Simple et assez.

YinPeng.Wei
la source
3
Il est difficile de justifier cette approche quand il y a une réelle chance de collision d'identité ...
Shadow
-7

Cela peut également être réalisé en utilisant ce modèle (Vue 2.0 v-bind), alors disons que vous avez une liste d'éléments à parcourir et que vous souhaitez donner des identifiants uninque à un élément dom.

new Vue({

  el:body,
  data: {
     myElementIds : [1,2,3,4,5,6,8]
   }
})

HTML

<div v-for="id in myElementIds">
    <label v-bind:for="id">Label text for {{id}}</label>
    <input v-bind:id="id" type="text" />
<div> 

J'espère que ça aide

pitaside
la source
8
Vous définissez simplement l'ID dans le tableau. Ne résout pas du tout la question initiale.
arminrosu