Vue.js: Her bileşen örneği için benzersiz bir kimlik nasıl belirlenir?


115

Vue.js ile bir etiket ve bir girdi içeren bir bileşen oluşturmak istiyorum. Örneğin :

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

Her bileşen örneği için nasıl benzersiz bir kimlik belirleyebilirim?

Teşekkür ederim.



Önceki yorumu daha önce görmemiştim, bunun için npm'de vue-unique-id Vue eklentisini de yayınladım .
bernie

Yanıtlar:


175

Her bileşenin, olarak erişilebilen benzersiz bir kimliği vardır 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>

Kimlikler üzerinde daha fazla kontrol istiyorsanız, örneğin bunları bir ana bileşenin içinde oluşturabilirsiniz.


readyYöntemin Vue 2.0 ve üzeri sürümlerde kaldırıldığını unutmayın . readyYöntem uygulanmadığında çok kafam karışmıştı . stackoverflow.com/a/40209796/126751
Brendan Wood

1
... ve databir nesne döndüren bir işlev olmalıdır: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
arminrosu

3
Ne yazık ki, bu geçerli olmadığı için TypeScript'te çalışmaz this._uid. Bunun yerine kimliğinizi kendiniz oluşturun, örneğin uuid4'epublic id = uuid4(); bakın .
Erik Vullings

2
Mount () yönteminden erişmeye çalıştığımda kimliğin DOM'da ayarlandığından emin olmak için ilklendirmeyi beforeMount () yöntemine koymak zorunda kaldım.
Stéphane Gerber


34

Nihat'ın görüşüne göre (yukarıda): Evan _uid'i kullanmamanızı tavsiye ettiniz: "vm _uid dahili kullanım için ayrılmıştır ve onu gizli tutmak (ve kullanıcı kodunda ona güvenmemek) önemlidir, böylece değiştirme esnekliğini koruyabiliriz. gelecekteki potansiyel kullanım durumları için davranış. ... UID'leri kendiniz oluşturmanızı öneririm [bir modül, global bir karışım, vb. kullanarak] "

UID'yi oluşturmak için bu GitHub sayısında önerilen karışımı kullanmak daha iyi bir yaklaşım gibi görünüyor:

let uuid = 0;

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

ilgili GitHub sorununa bir bağlantı burada çok yararlı olacaktır
Damon

1
Evan'ın _id kullanımına karşı tavsiyede bulunduğu GitHub sorunu: github.com/vuejs/vue/issues/5886#issuecomment-308625735
jannej

19

Güncelleme: Kod ._uid, örnekte özellik yoksa bir hata atar , böylece Vue tarafından sağlanmışsa özel veya yeni bir benzersiz kimlik özelliğini kullanmak için onu güncelleyebilirsiniz.

Zxzak'ın cevabı harika olsa da; _uidyayınlanmış bir API özelliği değildir. İleride değişmesi durumunda baş ağrısından kurtulmak için aşağıdaki gibi bir eklenti çözümü ile kodunuzu tek bir değişiklikle güncelleyebilirsiniz.

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

Bu hala kendi cevabınızda aleyhinize tavsiye edilen kullanıcı kimliğini kullanıyor. Lütfen kötü uygulamaları savunan yanıtlar göndermeyin. Bu cevap kaldırılmalıdır.
Hibrit web geliştirici

2
Evet, ancak yayınlanan API'nin değiştirilmesi / kaldırılması durumunda, kodun tamamında yalnızca bir yeri değiştirmeleri gerekecektir. Diğer yanıtta, bileşen başına yapıldı. Bunu başlıkta zaten vurguladım.
Nihat

Ayrıca, _uidözelliği artık mevcut olmadığında hata verecek şekilde kodu güncelledim .
Nihat

14

Güncelleme

Bunun için vue-unique-id Vue eklentisini npm'de yayınladım .

Cevap

Diğer çözümlerden hiçbiri, bileşeninizde birden fazla form öğesi olması gerekliliğini karşılamaz. İşte benim daha önce verilen cevaplara dayanan bir eklenti:

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

Bu, dahili kullanım için ayrılmış dahili _uidözelliğe bağlı değildir .

Bileşeninizde şu şekilde kullanın:

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

Bunun gibi bir şey üretmek için:

<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

Sonra kodunuzda ...

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

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

Bu şekilde, tüm lodash kütüphanesini yüklemiyor, hatta tüm kütüphaneyi kaydetmiyorsunuz node_modules.


2

Vue2'de v-bind kullanın.

Bir anket için bir nesnem olduğunu söyle

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

Gitmeniz gereken şey v-for="(option, index) in poll.body.options", indexv-bind içinde kullanmaktır .
Warre Buysse

1

Cevaplarda görmediğim basit bir yaklaşım:

<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'nin yaratıcısı, _uid'i kullanmaktan kaçınmanız gerektiğini söylüyor çünkü bu dahili kullanım içindir ve bir gün onu kaldırabilir, yeniden adlandırabilir veya davranışını değiştirebilir.
Omid Sadeghi

1
Teşekkürler, bunun doğru olduğunu düşünüyorum. Kodu farklı bir çözümle güncelledim, umarım hala yeterince basittir. Her neyse, bu örneğin fikri hesaplanmış bir özellik kullanmaktı.
Cristi Draghici

Lodash'tan gelen uniqueId bence en iyi yaklaşım
Giorgio Tempesta

1

Herhangi bir eklenti olmadan TypeScript kullanıyorsanız, sınıf bileşeninize statik bir kimlik ekleyebilir ve created () yönteminde bunu artırabilirsiniz. Her bileşenin benzersiz bir kimliği olacaktır (aynı ucu kullanan başka bileşenlerle çarpışmayı önlemek için bir dize öneki ekleyin)

<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

Bu paket, birden çok bileşende DOM'nuzda benzersiz olmayan kimliklere sahip olmanın altında yatan sorun için iyi bir çözüm gibi görünüyor:

vue-uniq-kimlikleri

Bileşenleri kullanma eğilimi. Bileşenler havalı, küçük, açık, kullanımı kolay ve modüler. İd özelliği gelene kadar.

Bazı HTML etiketi nitelikleri, label [for], input [form] ve birçok aria- * niteliği gibi bir id özelliği kullanılmasını gerektirir. Ve id ile ilgili sorun, modüler olmamasıdır. Sayfadaki birkaç kimlik özelliği aynı değere sahipse, birbirlerini etkileyebilirler.

VueUniqIds bu sorundan kurtulmanıza yardımcı olur. Özelliği kolay okunur tutarken benzersiz dizge ekleyerek değerin otomatik olarak değiştirildiği id ile ilgili yönergeler kümesi sağlar.


-4

Kullanıcı kimliğiniz başka bir bileşen tarafından kullanılmıyorsa, bir fikrim var.

uid: Math.random()

Basit ve yeterli.


3
Gerçek bir kimlik çarpışması şansı olduğunda bu yaklaşımı haklı çıkarmak zor ...
Shadow

-7

Bu desen kullanılarak da elde edilebilir (Vue 2.0 v-bind), diyelim ki üzerinde yinelenecek öğeler listesi var ve bazı dom element uninque id'leri vermek istiyorsunuz.

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> 

Umarım yardımcı olur


8
Siz sadece dizideki kimliği tanımlıyorsunuz. Orijinal soruyu hiç çözmüyor.
arminrosu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.