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

我想用 Vue.js 创建一个包含 labelinput的组件,例如:

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

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

165672 次浏览

每个组件都有一个惟一的 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 有更多的控制,可以在父组件中生成它们。

也可以使用这种模式(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>

希望能有帮助

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

更新: 如果实例中不存在 ._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");
}
});
}
});

对于 Nihat 的观点(上文) : Evan You 建议不要使用 _ uid: “ vm _ uid 是为内部使用保留的,保持它的私有性(而不是在用户代码中依赖它)很重要,这样我们才能保持灵活性,以便在未来的潜在用例中改变它的行为。... 我建议自己生成 UID [使用模块、全局混合等]”

GitHub 的问题中使用建议的 mix 生成 UID 似乎是一种更好的方法:

let uuid = 0;


export default {
beforeCreate() {
this.uuid = uuid.toString();
uuid += 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>

更新

我出版了 Vue-only-id Vue 插件

回答我

其他解决方案都不能满足组件中包含多个表单元素的要求。下面是我对一个插件的看法,它建立在先前给出的答案之上:

Vue.use((Vue) => {
// Assign a unique id to each component
let uidCounter = 0;
Vue.mixin({
beforeCreate: function() {
this.uidCounter = uidCounter.toString();
uidCounter += 1;
},
});


// Generate a component-scoped id
Vue.prototype.$id = function(id) {
return "uid-" + this.uidCounter + "-" + 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" />

如果您的 uid 没有被其他组件使用,我有一个想法。

uid: Math.random()

简单明了。

对于在 DOM 中跨多个组件使用非唯一 ID 的潜在问题,这个包似乎是一个很好的解决方案:

Vue-uniq-ids

使用组件是一种趋势。组件很酷,他们是小,明显,易于使用和模块化。直到遇到 id 属性。

有些 HTML 标记属性需要使用 id 属性,比如 label [ for ]、 input [ form ]和许多 aria-* 属性。Id 的问题在于它不是模块化的。如果页面上的几个 id 属性具有相同的值,它们可以相互影响。

VueUniqIds 可以帮助您解决这个问题。它提供了一组与 id 相关的指令,通过添加惟一字符串来自动修改这些指令的值,同时保持属性易于阅读。

npm i -S lodash.uniqueid

那么在你的代码里。

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


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

这样,您就不会加载整个 loash 库,甚至不会将整个库保存到 node_modules

如果您正在使用 TypeScript,而不使用任何插件,那么您可以简单地在您的类组件中添加一个静态 id,然后在 create ()方法中增加它。每个组件都有一个惟一的 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>

这似乎工作,我使用 https://www.npmjs.com/package/uuid

生成输出的例子: 元素: 47bfe557-d75f-455c-9a37-85b7935b297b

包裹 Json

"dependencies": {
"uuid": "^8.3.2"
},

组件 Vue

v-if="element"

...

import { v4 as uuidv4 } from 'uuid';

...

data() {
return {
element: null,
}
}

...

mounted() {
this.element = uuidv4();
}

这似乎对我在 nuxtjs 中使用有效

Https://www.npmjs.com/package/uuid

生成输出的例子: 元素: 47bfe557-d75f-455c-9a37-85b7935b297b

包裹 Json

"dependencies": {
"uuid": "^8.3.2"
},

在孩子的组成部分,可能不是最好的方式,但似乎工作

...

<ComponentName v-if="element" />

...

import { v4 as uuidv4 } from 'uuid';

...

data() {
return {
element: null,
}
}

...

mounted() {
this.element = uuidv4();
}

我发现的最简单的方法是通过全局 Mixin 手动创建 UUID (uuid package)。这样,您就不会依赖于任何可能在未来发生变化或被弃用的东西,比如 this._uid

您首先必须安装 uuid软件包:

npm i uuid

然后,在 main.js文件中创建一个全局 Mixin:

// rest of imports


import { v4 as uuidv4 } from 'uuid';


const app = Vue.createApp(App);


app.mixin({
data() {
return {
componentId: uuidv4()
}
},
});


app.use(store).use(router).mount('#app');

下面是你如何把它变成一个组件:

<template>
<div>
<h1>\{\{ componentId }}</h1>
<button @click="printId()">click me for componentId.</button>
</div>
</template>


<script>
export default {
methods: {
printId: function() {
console.log(this.componentId);
}
}
}
</script>

根据 MDN,您只需要创建一个隐式 标签绑定。

<label>
Label text
<input type="text" />
</label>

这样你甚至不需要分配 ID。

对于 Vue.js v3,你可以这样得到 id:

在模板 : \{\{ $.uid }}

脚本 : this.$.uid

或者使用你自己的功能或混合它们:

this.componentUid = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);

这将返回例如:

A174375-5b75-4919-acd0-980fcd54003c