Vue.js: ¿Cómo establecer una ID única para cada instancia de componente?


115

Quiero crear un componente con Vue.js que contenga una etiqueta y una entrada. por ejemplo :

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

¿Cómo puedo establecer un ID único para cada instancia de componente?

Gracias.


Hay varios paquetes / mixins que puede consultar: vue-ucid , vue-component-id , vue-uniq-ids .
— str

Como no había visto el comentario anterior antes, también publiqué el complemento vue-unique-id Vue para esto en npm .
— bernie

Respuestas:


175

Cada componente tiene una identificación única a la que se puede acceder como 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 desea más control sobre los identificadores, puede, por ejemplo, generarlos dentro de un componente principal.


Tenga en cuenta que el readymétodo se eliminó en Vue 2.0 y superior. Estaba muy confundido cuando el readymétodo no se estaba ejecutando. stackoverflow.com/a/40209796/126751
— Brendan Wood

1
... y datadebe ser una función que devuelva un objeto: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
— arminrosu

3
Desafortunadamente, esto no funciona en TypeScript, ya this._uidque no es válido. En su lugar, genere su ID usted mismo, por ejemplo public id = uuid4();, consulte uuid4 .
— Erik Vullings

2
Tuve que poner la inicialización en el método beforeMount () para asegurarme de que la identificación estaba configurada en el DOM cuando intenté acceder a ella desde el método installed ().
— Stéphane Gerber


34

Al punto de Nihat (arriba): Evan You ha desaconsejado el uso de _uid: "El vm _uid está reservado para uso interno y es importante mantenerlo en privado (y no confiar en él en el código de usuario) para que podamos mantener la flexibilidad de cambiar su comportamiento para posibles casos de uso futuros ... Sugeriría generar UID usted mismo [usando un módulo, un mixin global, etc.] "

Usar el mixin sugerido en este problema de GitHub para generar el UID parece un mejor enfoque:

let uuid = 0;

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

un enlace al problema pertinente de GitHub sería muy útil aquí
— Damon

1
Aquí está el problema de GitHub donde Evan desaconseja el uso de _id: github.com/vuejs/vue/issues/5886#issuecomment-308625735
— jannej

19

Actualización: el código arrojará un error si la ._uidpropiedad no existe en la instancia para que pueda actualizarla para usar algo personalizado o una nueva propiedad de identificación única si la proporciona Vue.

Aunque la respuesta de zxzak es genial; _uidno es una propiedad api publicada. Para ahorrar un dolor de cabeza en caso de que cambie en el futuro, puede actualizar su código con un solo cambio con una solución de complemento como la siguiente.

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

Esto todavía está usando el uid, que en su propia respuesta reconoce que se desaconseja. No publique respuestas que defiendan las malas prácticas. Esta respuesta debería eliminarse.
— Desarrollador web híbrido

2
Sí, pero en caso de que la API publicada se cambie / elimine, tendrán que cambiar solo un lugar en todo el código. En la otra respuesta, fue por componente. Ya lo enfaticé en el título.
— Nihat

Además, acabo de actualizar el código para que arroje un error en caso de que la _uidpropiedad ya no exista.
— Nihat

14

Actualizar

Publiqué el vue-única-id Vue Plugin para esto en la NGP .

Responder

Ninguna de las otras soluciones aborda el requisito de tener más de un elemento de formulario en su componente. Aquí está mi opinión sobre un complemento que se basa en respuestas dadas anteriormente:

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

Esto no depende de la _uidpropiedad interna que está reservada para uso interno .

Úselo así en su componente:

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

Para producir algo como esto:

<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

Luego, en tu código ...

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

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

De esta manera, no cargará toda la biblioteca lodash, ni siquiera guardará toda la biblioteca en node_modules.


2

En Vue2, use v-bind.

Di que tengo un objeto para una encuesta

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

Lo que debes buscar es v-for="(option, index) in poll.body.options"y usar indexen tu v-bind.
— Warre Buysse

1

Un enfoque simple que no he visto en las respuestas es:

<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
El creador de Vue.js dice que debes evitar usar _uid porque es para uso interno y algún día pueden eliminarlo o renombrarlo o cambiar su comportamiento.
— Omid Sadeghi

1
Gracias, creo que es correcto. He actualizado el código con una solución diferente, con suerte todavía lo suficientemente simple. De todos modos, la idea de este ejemplo era utilizar una propiedad calculada.
— Cristi Draghici

uniqueId de lodash es el mejor enfoque en mi opinión
— Giorgio Tempesta

1

Si está utilizando TypeScript, sin ningún complemento, simplemente puede agregar una identificación estática en su componente de clase e incrementarla en el método created (). Cada componente tendrá una identificación única (agregue un prefijo de cadena para evitar la colisión con otros componentes que usan la misma punta)

<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

Este paquete parece ser una buena solución para el problema subyacente de tener ID no únicos en su DOM en múltiples componentes:

vue-uniq-ids

Es una tendencia utilizar componentes. Los componentes son geniales, son pequeños, obvios, fáciles de usar y modulares. Hasta que se trata de la propiedad id.

Algunos atributos de etiquetas HTML requieren el uso de una propiedad id, como label [for], input [form] y muchos de los atributos aria- *. Y el problema con la identificación es que no es modular. Si varias propiedades de identificación en la página tienen el mismo valor, pueden afectarse entre sí.

VueUniqIds le ayuda a deshacerse de este problema. Proporciona el conjunto de directivas relacionadas con la identificación cuyo valor se modifica automáticamente agregando una cadena única mientras se mantiene el atributo fácil de leer.


-4

Si su uid no es usado por otro componente, tengo una idea.

uid: Math.random()

Simple y suficiente.


3
Es difícil justificar este enfoque cuando existe una posibilidad real de colisión de identificación ...
— Shadow

-7

También se puede lograr usando este patrón (Vue 2.0 v-bind), así que digamos que tiene una lista de elementos para iterar y desea dar algunos identificadores uninque de elementos 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> 

Espero eso ayude


8
Simplemente está definiendo el ID en la matriz. No resuelve la pregunta original en absoluto.
— arminrosu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.