Vue.js: จะตั้ง ID เฉพาะสำหรับแต่ละอินสแตนซ์ของคอมโพเนนต์ได้อย่างไร?


115

ฉันต้องการสร้างคอมโพเนนต์ด้วย Vue.js ที่มีเลเบลและอินพุต ตัวอย่างเช่น :

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

ฉันจะตั้งรหัสเฉพาะสำหรับแต่ละอินสแตนซ์ของคอมโพเนนต์ได้อย่างไร

ขอบคุณ.


: มีหลายแพคเกจ mixins ซึ่งคุณสามารถมองเข้าไปมี / vue-ucid , Vue องค์ประกอบ-ID , Vue-UNIQ-รหัส
str

ไม่เห็นมีความคิดเห็นก่อนหน้านี้ก่อนผมยังตีพิมพ์ปลั๊กอิน vue ซ้ำกัน-ID Vue สำหรับนี้ NPM
bernie

คำตอบ:


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

1
... และdataต้องเป็นฟังก์ชันที่ส่งคืนวัตถุ: vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
arminrosu

3
ขออภัยสิ่งนี้ใช้ไม่ได้ใน TypeScript เนื่องจากthis._uidไม่ถูกต้อง แทนที่จะสร้าง ID ของคุณด้วยตัวคุณเองเช่น public id = uuid4();ดูuuid4
Erik Vullings

2
ฉันต้องใส่ค่าเริ่มต้นในเมธอด beforeMount () เพื่อให้แน่ใจว่า id ถูกตั้งค่าใน DOM เมื่อฉันพยายามเข้าถึงจากเมธอด mount ()
Stéphane Gerber


34

ในประเด็นของ Nihat (ด้านบน): Evan คุณได้แนะนำไม่ให้ใช้ _uid: "vm _uid สงวนไว้สำหรับการใช้งานภายในและสิ่งสำคัญคือต้องเก็บไว้เป็นส่วนตัว (และไม่ต้องพึ่งพารหัสผู้ใช้) เพื่อให้เรามีความยืดหยุ่นในการเปลี่ยนแปลง พฤติกรรมสำหรับกรณีการใช้งานที่อาจเกิดขึ้นในอนาคต ... ฉันขอแนะนำให้สร้าง UID ด้วยตนเอง [โดยใช้โมดูลมิกซ์อินส่วนกลาง ฯลฯ ] "

การใช้ mixin ที่แนะนำในปัญหา GitHub นี้เพื่อสร้าง UID ดูเหมือนจะเป็นแนวทางที่ดีกว่า:

let uuid = 0;

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

ลิงก์ไปยังปัญหา GitHub ที่เกี่ยวข้องจะมีประโยชน์มากที่นี่
Damon

1
นี่คือปัญหา GitHub ที่ Evan ไม่แนะนำให้ใช้ _id: github.com/vuejs/vue/issues/5886#issuecomment-308625735
ม.ค.

19

อัปเดต: รหัสจะแสดงข้อผิดพลาดหาก._uidคุณสมบัติไม่มีอยู่ในอินสแตนซ์เพื่อให้คุณสามารถอัปเดตเพื่อใช้คุณสมบัติรหัสเฉพาะที่กำหนดเองหรือใหม่ได้หาก 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-unique-id Vue สำหรับสิ่งนี้ใน npmNPM

ตอบ

ไม่มีโซลูชันอื่นใดที่ตอบสนองความต้องการของการมีองค์ประกอบฟอร์มมากกว่าหนึ่งองค์ประกอบในส่วนประกอบของคุณ นี่คือสิ่งที่ฉันใช้ในปลั๊กอินที่สร้างจากคำตอบที่ให้ไว้ก่อนหน้านี้:

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 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 เพราะใช้สำหรับการใช้งานภายในและสักวันพวกเขาอาจลบหรือเปลี่ยนชื่อหรือเปลี่ยนพฤติกรรม
Omid Sadeghi

1
ขอบคุณฉันคิดว่าถูกต้อง ฉันได้อัปเดตโค้ดด้วยวิธีอื่นแล้วหวังว่าจะยังง่ายพอ อย่างไรก็ตามแนวคิดของตัวอย่างนี้คือการใช้คุณสมบัติที่คำนวณได้
Cristi Draghici

uniqueId จาก lodash เป็นแนวทางที่ดีที่สุดในความคิดของฉัน
Giorgio Tempesta

1

หากคุณใช้ TypeScript โดยไม่มีปลั๊กอินใด ๆ คุณสามารถเพิ่มรหัสคงที่ในองค์ประกอบคลาสของคุณและเพิ่มขึ้นในเมธอด 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

แพคเกจนี้ดูเหมือนจะเป็นทางออกที่ดีสำหรับปัญหาพื้นฐานของการมี ID ที่ไม่ซ้ำกันใน DOM ของคุณในหลายองค์ประกอบ:

vue-uniq-id

เป็นเทรนด์ในการใช้ส่วนประกอบ ส่วนประกอบนั้นเจ๋งมีขนาดเล็กชัดเจนใช้งานง่ายและเป็นโมดูลาร์ จนกว่าจะถึงคุณสมบัติ id

แอตทริบิวต์แท็ก HTML บางอย่างต้องใช้คุณสมบัติ id เช่น label [for], input [form] และแอตทริบิวต์ aria- * จำนวนมาก และปัญหาเกี่ยวกับ id คือมันไม่ได้เป็นแบบแยกส่วน หากคุณสมบัติ id หลายรายการในเพจจะมีค่าเท่ากันก็สามารถส่งผลต่อกันและกันได้

VueUniqIds ช่วยคุณกำจัดปัญหานี้ มันมีชุดของคำสั่งที่เกี่ยวข้องกับ id ซึ่งค่าจะถูกแก้ไขโดยอัตโนมัติโดยการเพิ่มสตริงที่ไม่ซ้ำกันในขณะที่ทำให้การอ่านง่าย


-4

หากผู้อื่นไม่ได้ใช้ uid ของคุณฉันมีความคิด

uid: Math.random()

ง่ายและเพียงพอ


3
เป็นเรื่องยากที่จะปรับแนวทางนี้เมื่อมีโอกาสเกิดการชนกันของรหัส ...
เงา

-7

นอกจากนี้ยังสามารถทำได้โดยใช้รูปแบบนี้ (Vue 2.0 v-bind) ดังนั้นสมมติว่าคุณมีรายการที่ต้องทำซ้ำและคุณต้องการให้รหัส uninque ขององค์ประกอบ 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
คุณเพียงแค่กำหนด ID ในอาร์เรย์ ไม่สามารถแก้ปัญหาเดิมได้เลย
arminrosu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.