Vue.js: Jak ustawić unikalny identyfikator dla każdej instancji komponentu?

115

Chcę utworzyć komponent z Vue.js zawierający etykietę i dane wejściowe. na przykład :

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

Jak ustawić unikalny identyfikator dla każdej instancji składnika?

Dziękuję Ci.

PierreB
źródło
Istnieje kilka pakietów / mixinów, do których możesz zajrzeć: vue-ucid , vue-component-id , vue-uniq-ids .
str
Nie widząc wcześniej poprzedniego komentarza, opublikowałem również wtyczkę Vue vue-unique-id do tego na npm .
bernie

Odpowiedzi:

175

Każdy komponent ma unikalny identyfikator, do którego można uzyskać dostęp jako 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>

Jeśli chcesz mieć większą kontrolę nad identyfikatorami, możesz na przykład wygenerować je w komponencie nadrzędnym.

zxzak
źródło
Zauważ, że readymetoda została usunięta w Vue 2.0 i nowszych. Byłem bardzo zdezorientowany, gdy readymetoda nie była wykonywana. stackoverflow.com/a/40209796/126751
Brendan Wood
1
... i datamusi być funkcją, która zwraca obiekt: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
arminrosu
3
Niestety, to nie działa w TypeScript, ponieważ this._uidjest nieprawidłowe. Zamiast tego wygeneruj swój identyfikator samodzielnie, np. public id = uuid4();Zobacz uuid4 .
Erik Vullings
2
Musiałem umieścić inicjalizację w metodzie beforeMount (), aby upewnić się, że identyfikator został ustawiony w DOM, kiedy próbowałem uzyskać do niego dostęp z metody mount ().
Stéphane Gerber
34

Do punktu Nihata (powyżej): Evan Odradzasz używanie _uid: „Maszyna wirtualna _uid jest zarezerwowana do użytku wewnętrznego i ważne jest, aby zachować jej prywatność (i nie polegać na niej w kodzie użytkownika), aby zachować elastyczność w zmianie jej zachowanie dla potencjalnych przyszłych przypadków użycia. ... Sugerowałbym samodzielne wygenerowanie identyfikatorów UID [za pomocą modułu, globalnego miksu itp.] "

Korzystanie z sugerowanego miksera w tym problemie z GitHubem do generowania UID wydaje się lepszym podejściem:

let uuid = 0;

export default {
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
};
szakłak
źródło
bardzo przydatny byłby link do stosownego problemu z GitHubem
Damon
1
Oto problem z GitHub, w którym Evan odradza
jannej
19

Aktualizacja: kod zgłosi błąd, jeśli ._uidwłaściwość nie istnieje w instancji, dzięki czemu można ją zaktualizować, aby używała czegoś niestandardowego lub nowej unikalnej właściwości identyfikatora, jeśli jest dostarczana przez Vue.

Chociaż odpowiedź zxzaka jest świetna; _uidnie jest opublikowaną właściwością API. Aby zaoszczędzić sobie bólu głowy na wypadek, gdyby zmienił się w przyszłości, możesz zaktualizować kod za pomocą jednej zmiany za pomocą wtyczki, jak poniżej.

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
źródło
Nadal jest to uid, który w twojej własnej odpowiedzi jest odradzany. Nie publikuj odpowiedzi nawołujących do złych praktyk. Tę odpowiedź należy usunąć.
Hybrydowy programista sieciowy
2
Tak, ale w przypadku zmiany / usunięcia opublikowanego interfejsu API będą musieli zmienić tylko jedno miejsce w całym kodzie. W drugiej odpowiedzi dotyczyło to części. Podkreśliłem to już w tytule.
Nihat,
Ponadto właśnie zaktualizowałem kod, aby generował błąd w przypadku, gdy _uidwłaściwość już nie istnieje.
Nihat,
14

Aktualizacja

Opublikowałem wtyczkę Vue vue-unique-id do tego na npm .

Odpowiedź

Żadne z innych rozwiązań nie spełnia wymagania posiadania więcej niż jednego elementu formularza w komponencie. Oto moje podejście do wtyczki, która opiera się na wcześniej udzielonych odpowiedziach:

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

Nie zależy to od _uidwłaściwości wewnętrznej, która jest zarezerwowana do użytku wewnętrznego .

Użyj go w ten sposób w swoim komponencie:

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

Aby stworzyć coś takiego:

<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
źródło
3
npm i -S lodash.uniqueid

Następnie w swoim kodzie ...

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

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

W ten sposób nie ładujesz całej biblioteki lodash, ani nawet nie zapisujesz całej biblioteki do node_modules.

meconroy
źródło
2

W Vue2 użyj v-bind.

Powiedz, że mam obiekt do ankiety

  <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>
趙曉明
źródło
Powinieneś iść v-for="(option, index) in poll.body.options"i użyć indexw swoim v-bind'u.
Warre Buysse
1

Proste podejście, którego nie widziałem w odpowiedziach, to:

<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
źródło
1
Twórca Vue.js mówi, że powinieneś unikać używania _uid, ponieważ jest on do użytku wewnętrznego i pewnego dnia może go usunąć, zmienić jego nazwę lub zmienić jego zachowanie.
Omid Sadeghi
1
Dzięki, myślę, że to prawda. Zaktualizowałem kod za pomocą innego rozwiązania, mam nadzieję, że nadal jest wystarczająco proste. W każdym razie ideą tego przykładu było użycie obliczonej właściwości.
Cristi Draghici
uniqueId from lodash to moim zdaniem najlepsze podejście
Giorgio Tempesta
1

Jeśli używasz TypeScript, bez żadnej wtyczki, możesz po prostu dodać statyczny identyfikator do komponentu klasy i zwiększyć go w metodzie created (). Każdy komponent będzie miał unikalny identyfikator (dodaj prefiks ciągu, aby uniknąć kolizji z innymi komponentami, które używają tej samej końcówki)

<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
źródło
0

Ten pakiet wydaje się być dobrym rozwiązaniem podstawowego problemu z posiadaniem nieunikalnych identyfikatorów w Twoim DOM w wielu komponentach:

vue-uniq-ids

Stosowanie komponentów to trend. Komponenty są fajne, są małe, oczywiste, łatwe w użyciu i modułowe. Dopóki nie dojdzie do własności id.

Niektóre atrybuty znaczników HTML wymagają użycia właściwości id, np. Label [for], input [form] i wiele atrybutów aria- *. Problem z id polega na tym, że nie jest on modułowy. Jeśli kilka właściwości id na stronie ma tę samą wartość, mogą one na siebie wpływać.

VueUniqIds pomaga pozbyć się tego problemu. Dostarcza zestaw dyrektyw związanych z identyfikatorem, których wartość jest automatycznie modyfikowana przez dodanie unikalnego ciągu, przy czym atrbitue jest łatwy do odczytania.

tryforce
źródło
-4

Jeśli twój uid nie jest używany przez inny składnik, mam pomysł.

uid: Math.random()

Proste i wystarczające.

YinPeng.Wei
źródło
3
Trudno jest uzasadnić takie podejście, gdy istnieje realna szansa na kolizję identyfikatorów ...
Shadow
-7

Można to również osiągnąć za pomocą tego wzorca (Vue 2.0 v-bind), więc powiedzmy, że masz listę elementów do iteracji i chcesz nadać niektórym elementom dom niepowtarzalne identyfikatory.

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> 

Mam nadzieję, że to pomoże

pitaside
źródło
8
Po prostu definiujesz identyfikator w tablicy. W ogóle nie rozwiązuje pierwotnego pytania.
arminrosu