Vue.js: Как установить уникальный идентификатор для каждого экземпляра компонента?

115

Я хочу создать компонент с Vue.js, содержащий метку и ввод. например :

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

Как я могу установить уникальный идентификатор для каждого экземпляра компонента?

Спасибо.

PierreB
источник
Вы можете изучить несколько пакетов / миксинов : vue-ucid , vue-component-id , vue-uniq-ids .
str
Не видя ранее предыдущего комментария, я также опубликовал для этого плагин vue-unique-id Vue на npm .
Берни

Ответы:

175

Каждый компонент имеет уникальный идентификатор, к которому можно получить доступ как 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>

Если вам нужен больший контроль над идентификаторами, вы можете, например, сгенерировать их внутри родительского компонента.

Zxzak
источник
Обратите внимание, что этот readyметод был удален в Vue 2.0 и выше. Я был очень сбит с толку, когда readyметод не выполнялся. stackoverflow.com/a/40209796/126751
Брендан Вуд
1
... и dataдолжна быть функцией, возвращающей объект: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
arminrosu
3
К сожалению, в TypeScript это не работает, так как this._uidнедопустимо. Вместо этого создайте свой идентификатор самостоятельно, например public id = uuid4();, см. Uuid4 .
Erik Vullings
2
Мне пришлось поместить инициализацию в метод beforeMount (), чтобы убедиться, что идентификатор был установлен в DOM, когда я пытался получить к нему доступ из метода mount ().
Стефан Гербер
34

На точку зрения Нихата (см. Выше): Эван Ю посоветовал не использовать _uid: "vm _uid зарезервирован для внутреннего использования, и важно сохранить его конфиденциальность (и не полагаться на него в пользовательском коде), чтобы мы могли гибко изменять его поведение для потенциальных вариантов использования в будущем ... Я бы посоветовал самостоятельно генерировать UID [с помощью модуля, глобального миксина и т. д.] "

Использование предлагаемого миксина в этой проблеме GitHub для генерации UID кажется лучшим подходом:

let uuid = 0;

export default {
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
};
облепиха
источник
здесь была бы очень полезна ссылка на соответствующую проблему GitHub
Дэймон
1
Вот проблема GitHub, в которой Эван советует не использовать _id: github.com/vuejs/vue/issues/5886#issuecomment-308625735
jannej 03
19

Обновление: код выдает ошибку, если ._uidсвойство не существует в экземпляре, чтобы вы могли обновить его, чтобы использовать что-то настраиваемое или новое уникальное свойство id, если оно предоставлено Vue.

Хотя ответ zxzak великолепен; _uidне является опубликованным свойством API. Чтобы избавиться от головной боли на случай, если он изменится в будущем, вы можете обновить свой код всего одним изменением с помощью плагина, как показано ниже.

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");
            }
        });
    }
});
Нихат
источник
Это все еще использует uid, который в вашем собственном ответе не рекомендуется. Пожалуйста, не публикуйте ответы, пропагандирующие плохие практики. Этот ответ следует удалить.
Гибридный веб-разработчик
2
Да, но в случае изменения / удаления опубликованного API, им придется изменить только одно место во всем коде. В другом ответе это было для каждого компонента. Я уже подчеркивал это в названии.
Nihat
Кроме того, я только что обновил код, чтобы он выдавал ошибку, если _uidсвойство больше не существует.
Nihat
14

Обновить

Я опубликовал для этого плагин Vue vue-unique-id на npm .

Ответ

Ни одно из других решений не отвечает требованиям наличия более одного элемента формы в вашем компоненте. Вот мой взгляд на плагин, основанный на ранее полученных ответах:

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

Это не зависит от внутреннего _uidсвойства, которое зарезервировано для внутреннего использования .

Используйте это в своем компоненте так:

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

Чтобы произвести что-то вроде этого:

<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
источник
3
npm i -S lodash.uniqueid

Тогда в вашем коде ...

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

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

Таким образом, вы не загружаете всю библиотеку lodash или даже не сохраняете всю библиотеку в node_modules.

meconroy
источник
2

В Vue2 используйте v-bind.

Скажем, у меня есть объект для опроса

  <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>
趙曉明
источник
Вам следует пойти на это v-for="(option, index) in poll.body.options"и использовать indexв себе v-bind.
Warre Бейс
1

Простой подход, который я не видел в ответах:

<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
Создатель Vue.js говорит, что вам следует избегать использования _uid, потому что он предназначен для внутреннего использования, и когда-нибудь они могут удалить его, переименовать или изменить его поведение.
Омид Садеги
1
Спасибо, думаю, это правильно. Я обновил код другим решением, надеюсь, все еще достаточно простым. В любом случае идея этого примера заключалась в использовании вычисляемого свойства.
Cristi Draghici
uniqueId от lodash, на мой взгляд, лучший подход
Джорджио Темпеста
1

Если вы используете TypeScript без какого-либо плагина, вы можете просто добавить статический идентификатор в свой компонент класса и увеличить его в методе created (). Каждый компонент будет иметь уникальный идентификатор (добавьте строковый префикс, чтобы избежать столкновения с другими компонентами, которые используют тот же наконечник)

<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
источник
0

Этот пакет кажется хорошим решением основной проблемы наличия неуникальных идентификаторов в вашей DOM для нескольких компонентов:

vue-uniq-ids

Использование компонентов - это тенденция. Компоненты классные, они маленькие, очевидные, простые в использовании и модульные. Пока дело не доходит до свойства id.

Некоторые атрибуты тегов HTML требуют использования свойства id, например label [for], input [form] и многих атрибутов aria- *. Проблема с идентификатором в том, что он не модульный. Если несколько свойств id на странице будут иметь одинаковое значение, они могут влиять друг на друга.

VueUniqIds поможет вам избавиться от этой проблемы. Он предоставляет набор директив, связанных с идентификатором, значение которых автоматически изменяется путем добавления уникальной строки, сохраняя при этом удобочитаемость атрибута.

пытливый
источник
-4

Если ваш uid не используется другим компоментом, у меня есть идея.

uid: Math.random()

Просто и достаточно.

ИньПэн Вэй
источник
3
Трудно оправдать такой подход, когда есть реальная вероятность столкновения id ...
Shadow
-7

Этого также можно достичь с помощью этого шаблона (Vue 2.0 v-bind), поэтому предположим, что у вас есть список элементов, которые нужно перебирать, и вы хотите присвоить некоторому элементу 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> 

Надеюсь, поможет

питасайд
источник
8
Вы просто определяете идентификатор в массиве. Совершенно не решает исходный вопрос.
arminrosu