Vue.js: Wie wird eine eindeutige ID für jede Komponenteninstanz festgelegt?


115

Ich möchte eine Komponente mit Vue.js erstellen, die eine Beschriftung und eine Eingabe enthält. zum Beispiel :

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

Wie kann ich für jede Komponenteninstanz eine eindeutige ID festlegen?

Danke dir.


Es gibt verschiedene Pakete / Mixins, die Sie sich ansehen können: vue-ucid , vue-component-id , vue-uniq-ids .
Str

Nachdem ich den vorherigen Kommentar noch nicht gesehen hatte, veröffentlichte ich auch das vue-unique-id Vue-Plugin dafür auf npm .
Bernie

Antworten:


174

Jede Komponente hat eine eindeutige ID, auf die als zugegriffen werden kann 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>

Wenn Sie mehr Kontrolle über die IDs wünschen, können Sie diese beispielsweise in einer übergeordneten Komponente generieren.


Beachten Sie, dass die readyMethode in Vue 2.0 und höher entfernt wurde. Ich war sehr verwirrt, als die readyMethode nicht ausgeführt wurde. stackoverflow.com/a/40209796/126751
Brendan Wood

1
... und datamuss eine Funktion sein, die ein Objekt zurückgibt
arminrosu

3
Leider funktioniert dies in TypeScript nicht, da this._uides nicht gültig ist. Generieren Sie stattdessen Ihre ID selbst, z . B. public id = uuid4();siehe uuid4 .
Erik Vullings

2
Ich musste die Initialisierung in die beforeMount () -Methode einfügen, um sicherzustellen, dass die ID im DOM festgelegt wurde, als ich versuchte, über die mount () -Methode darauf zuzugreifen.
Stéphane Gerber


34

Zu Nihats Punkt (oben): Evan Sie haben von der Verwendung von _uid abgeraten: "Die vm _uid ist für den internen Gebrauch reserviert und es ist wichtig, sie privat zu halten (und sich nicht auf sie im Benutzercode zu verlassen), damit wir die Flexibilität behalten, sie zu ändern Verhalten für potenzielle zukünftige Anwendungsfälle ... Ich würde vorschlagen, UIDs selbst zu generieren [mithilfe eines Moduls, eines globalen Mixins usw.] "

Die Verwendung des in dieser GitHub-Ausgabe vorgeschlagenen Mixins zum Generieren der UID scheint ein besserer Ansatz zu sein:

let uuid = 0;

export default {
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
};

Ein Link zum relevanten GitHub-Problem wäre hier sehr nützlich
Damon

1
Hier ist das GitHub-Problem, bei dem Evan davon abrät, _id zu verwenden: github.com/vuejs/vue/issues/5886#issuecomment-308625735
jannej

19

Aktualisieren: Code gibt einen Fehler aus, wenn ._uidin der Instanz keine Eigenschaft vorhanden ist, sodass Sie sie aktualisieren können, um eine benutzerdefinierte oder neue eindeutige ID-Eigenschaft zu verwenden, sofern diese von Vue bereitgestellt wird.

Obwohl die Antwort von zxzak großartig ist; _uidist keine veröffentlichte API-Eigenschaft. Um Kopfschmerzen zu vermeiden, falls sie sich in Zukunft ändern sollten, können Sie Ihren Code mit nur einer Änderung mit einer Plugin-Lösung wie der folgenden aktualisieren.

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

Dies verwendet immer noch die UID, von der in Ihrer eigenen Antwort abgeraten wird. Bitte posten Sie keine Antworten, die schlechte Praktiken befürworten. Diese Antwort sollte entfernt werden.
Hybrid Web Dev

2
Ja, aber falls die veröffentlichte API geändert / entfernt wird, muss nur eine Stelle im gesamten Code geändert werden. In der anderen Antwort war es pro Komponente. Das habe ich bereits im Titel betont.
Nihat

Außerdem habe ich den Code soeben aktualisiert, dass ein Fehler ausgegeben wird, falls die _uidEigenschaft nicht mehr vorhanden ist.
Nihat

13

Aktualisieren

Ich habe das vue-unique-id Vue-Plugin dafür auf npm veröffentlicht .

Antworten

Keine der anderen Lösungen erfüllt die Anforderung, mehr als ein Formularelement in Ihrer Komponente zu haben. Hier ist meine Einstellung zu einem Plugin, das auf zuvor gegebenen Antworten aufbaut:

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

Dies hängt nicht von der internen _uidEigenschaft ab, die für den internen Gebrauch reserviert ist .

Verwenden Sie es so in Ihrer Komponente:

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

Um so etwas zu produzieren:

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

3
npm i -S lodash.uniqueid

Dann in Ihrem Code ...

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

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

Auf diese Weise laden Sie nicht die gesamte Lodash-Bibliothek oder speichern sogar die gesamte Bibliothek in node_modules.


2

Verwenden Sie in Vue2 v-bind.

Angenommen, ich habe ein Objekt für eine Umfrage

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

Was Sie anstreben sollten, ist v-for="(option, index) in poll.body.options", und verwenden indexSie in Ihrem V-Bind.
Warre Buysse

1

Ein einfacher Ansatz, den ich in den Antworten nicht gesehen habe, ist:

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

1
Der Ersteller von Vue.js sagt, Sie sollten die Verwendung von _uid vermeiden, da es für den internen Gebrauch bestimmt ist. Eines Tages können sie es entfernen oder umbenennen oder sein Verhalten ändern.
Omid Sadeghi

1
Danke, ich denke das ist richtig. Ich habe den Code mit einer anderen Lösung aktualisiert, hoffentlich immer noch einfach genug. Die Idee dieses Beispiels war jedenfalls, eine berechnete Eigenschaft zu verwenden.
Cristi Draghici

uniqueId von lodash ist meiner Meinung nach der beste Ansatz
Giorgio Tempesta

1

Wenn Sie TypeScript ohne Plugin verwenden, können Sie Ihrer Klassenkomponente einfach eine statische ID hinzufügen und diese in der create () -Methode erhöhen. Jede Komponente hat eine eindeutige ID (fügen Sie ein Zeichenfolgenpräfix hinzu, um eine Kollision mit anderen Komponenten zu vermeiden, die denselben Tipp verwenden).

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

0

Dieses Paket scheint eine gute Lösung für das zugrunde liegende Problem zu sein, nicht eindeutige IDs in Ihrem DOM über mehrere Komponenten hinweg zu haben:

vue-uniq-ids

Es ist ein Trend, Komponenten zu verwenden. Komponenten sind cool, klein, offensichtlich, einfach zu bedienen und modular. Bis es zur id-Eigenschaft kommt.

Für einige HTML-Tag-Attribute muss eine id-Eigenschaft verwendet werden, z. B. label [for], input [form] und viele aria- * -Attribute. Und das Problem mit der ID ist, dass sie nicht modular ist. Wenn mehrere ID-Eigenschaften auf der Seite denselben Wert haben, können sie sich gegenseitig beeinflussen.

VueUniqIds hilft Ihnen, dieses Problem zu beseitigen. Es enthält eine Reihe von ID-bezogenen Anweisungen, deren Wert automatisch geändert wird, indem eine eindeutige Zeichenfolge hinzugefügt wird, während das Attribut leicht lesbar bleibt.


-4

Wenn Ihre UID nicht von anderen Komponenten verwendet wird, habe ich eine Idee.

uid: Math.random()

Einfach und genug.


3
Es ist schwierig, diesen Ansatz zu rechtfertigen, wenn eine echte Chance auf eine ID-Kollision besteht ...
Shadow

-7

Dies kann auch mit diesem Muster erreicht werden (Vue 2.0 v-bind). Nehmen wir also an, Sie haben eine Liste von Elementen, über die Sie iterieren können, und Sie möchten einige dom-Element-Uninque-IDs angeben.

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> 

Ich hoffe es hilft


8
Sie definieren einfach die ID im Array. Löst die ursprüngliche Frage überhaupt nicht.
Arminrosu
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.