Vue.js:如何为每个组件实例设置唯一的ID?


Answers:


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进行更多控制,可以例如在父组件内部生成ID。


请注意,该ready方法已在Vue 2.0及更高版本中删除。当ready方法不执行时,我感到非常困惑。stackoverflow.com/a/40209796/126751
Brendan Wood

1
...,并且data必须是返回对象的函数:vuejs.org/v2/guide/components.html#data-
arminrosu

3
不幸的是,这在TypeScript中不起作用,因为this._uid无效。相反,请自己生成您的ID,例如 public id = uuid4();,参见uuid4
Erik Vullings

2
我必须将初始化放在beforeMount()方法中,以确保在尝试从mount()方法访问它时在DOM中设置了ID。
斯特凡格柏


34

关于Nihat(以上):Evan您建议不要使用_uid:“ vm _uid保留供内部使用,将其保持私有状态(而不是在用户代码中依赖它)很重要,这样我们才能灵活地更改其潜在的未来用例的行为。...我建议您自己生成UID(使用模块,全局mixin等)”

此GitHub问题中使用建议的mixin 生成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
jannej

19

更新: 如果._uid实例中不存在属性,则代码将引发错误,以便您可以更新它以使用Vue提供的自定义属性或新的唯一id属性。

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

13

更新资料

在npm上发布了vue-unique-id Vue插件

回答

其他解决方案都不能满足在组件中具有多个表单元素的要求。这是我对基于先前给出的答案的插件的看法:

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

我认为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标记属性需要使用id属性,例如label [for],input [form]和许多aria- *属性。id的问题在于它不是模块化的。如果页面上的多个id属性具有相同的值,则它们可能会相互影响。

VueUniqIds可帮助您摆脱此问题。它提供了一组与ID相关的指令,该指令的值通过添加唯一的字符串自动修改,同时保持属性易于阅读。


-4

如果您的uid不被其他工具使用,我有个主意。

uid: Math.random()

简单而足够。


3
当真的有ID碰撞的机会时,很难证明这种方法的合理性……
Shadow

-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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.