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


115

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

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

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

Спасибо.


Вы можете изучить несколько пакетов / миксинов : 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>

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


Обратите внимание, что этот 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" />

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.


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>

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.