Vue.js:各コンポーネントインスタンスに一意のIDを設定するにはどうすればよいですか?


115

ラベルと入力を含むVue.jsでコンポーネントを作成したいと思います。例えば ​​:

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

各コンポーネントインスタンスに一意のIDを設定するにはどうすればよいですか?

ありがとうございました。


調べることができるいくつかのパッケージ/ミックスインがあります:vue-ucidvue-component-idvue-uniq-ids
str

以前のコメントを見たことがないので、このためのvue-unique-id Vueプラグインもnpmで公開しました。
バーニー

回答:


175

各コンポーネントには、としてアクセスできる一意のIDがあります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>

たとえば、IDをより詳細に制御したい場合は、親コンポーネント内で生成します。


この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無効です。代わりに、自分でIDを生成します。たとえば public id = uuid4();uuid4を参照してください。
エリック・ヴァリングス2017年

2
マウントされた()メソッドからアクセスしようとしたときに、DOMにIDが設定されていることを確認するために、beforeMount()メソッドに初期化を配置する必要がありました。
ステファン・ガーバー


34

Nihatの要点(上記):Evanあなたは_uidの使用を推奨していません。潜在的な将来のユースケースの動作...自分でUIDを生成することをお勧めします[モジュール、グローバルミックスインなどを使用して]。 "

このGitHubの問題で提案されているミックスインを使用してUIDを生成することは、より良いアプローチのようです。

let uuid = 0;

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

関連するGitHubの問題へのリンクは、ここで非常に役立ちます
デイモン

1
これがGitHubの問題で、Evanが_idを使用しないようにアドバイスしています:github.com/vuejs/vue/issues/5886#issuecomment-308625735
jannej

19

更新:._uidプロパティがインスタンスに存在しない 場合、コードはエラーをスローします。Vueから提供された場合、カスタムまたは新しい一意のIDプロパティを使用するように更新できます。

zxzakの答えは素晴らしいですが; _uidは公開されたAPIプロパティではありません。頭痛の種を将来的に変更する場合に備えて、以下のようなプラグインソリューションを使用して、1回の変更でコードを更新できます。

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を使用していますが、これはあなた自身の回答では認められていません。不正行為を支持する回答を投稿しないでください。この回答は削除する必要があります。
ハイブリッドWeb

2
はい。ただし、公開されたAPIが変更または削除された場合、コード全体で1か所だけ変更する必要があります。他の答えでは、それはコンポーネントごとでした。私はすでにタイトルでそれを強調しました。
Nihat

また、_uidプロパティが存在しない場合にエラーをスローするようにコードを更新しました。
Nihat

14

更新

このためvue-unique-id Vueプラグインを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バインドで使用することです。
Warre Buysse

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は内部で使用するものであり、いつかは削除したり、名前を変更したり、動作を変更したりする可能性があるため、_uidの使用は避けてください。
Omid Sadeghi

1
ありがとう、それは正しいと思います。私は別の解決策でコードを更新しましたが、うまくいけばまだ簡単です。とにかく、この例のアイデアは、計算されたプロパティを使用することでした。
クリスティDraghici

lodashのuniqueIdは私の意見では最良のアプローチです
Giorgio Tempesta

1

プラグインなしでTypeScriptを使用している場合は、クラスコンポーネントに静的IDを追加して、created()メソッドでそれをインクリメントできます。各コンポーネントには一意のIDがあります(同じヒントを使用する別のコンポーネントとの衝突を避けるために文字列の接頭辞を追加します)

<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に一意でないIDが存在するという根本的な問題に対する優れたソリューションのようです。

vue-uniq-ids

コンポーネントを使用する傾向です。コンポーネントはクールで、小さく、明白で、使いやすく、モジュール式です。それがidプロパティになるまで。

一部のHTMLタグ属性では、label [for]、input [form]などのidプロパティと多くのaria- *属性を使用する必要があります。そして、idの問題は、それがモジュール式ではないことです。ページ上のいくつかのidプロパティが同じ値を持つ場合、それらは互いに影響を与える可能性があります。

VueUniqIdsは、この問題を取り除くのに役立ちます。これは、属性を読みやすくしつつ、一意の文字列を追加することによって値が自動的に変更されるid関連のディレクティブのセットを提供します。


-4

あなたのuidが他のコンポーネントで使用されていない場合、私は考えがあります。

uid: Math.random()

シンプルで十分です。


3
それは...、IDの衝突の本当のチャンスがあるときに、このアプローチを正当化するのは難しい
シャドウ

-7

これは、このパターン(Vue 2.0 v-bind)を使用しても実現できるため、反復処理するアイテムのリストがあり、いくつかのdom要素に非インクIDを指定するとします。

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
単に配列にIDを定義しているだけです。元の質問をまったく解決しません。
arminrosu 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.