每个组件都有一个唯一的 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,您可以在父组件内生成它们。
对于尼哈特的观点(上):
Evan You 建议不要使用 _uid:
vm _uid 保留供内部使用,保持其私有(并且不要在用户代码中依赖它)非常重要,这样我们就可以灵活地更改其行为以适应未来潜在的用例。 ...我建议自己生成 UID [使用模块、全局 mixin 等]
使用此 GitHub 问题中建议的 mixin 来生成 UID 似乎是更好的方法:
let uuid = 0;
export default {
beforeCreate() {
this.uuid = uuid.toString();
uuid += 1;
},
};
我在 npm 上发布了 vue-unique-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
属性,代码将抛出错误,以便您可以更新它以使用自定义或新的唯一 id 属性(如果由 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");
}
});
}
});
npm i -S lodash.uniqueid
然后在你的代码中...
<script>
const uniqueId = require('lodash.uniqueid')
export default {
data () {
return {
id: ''
}
},
mounted () {
this.id = uniqueId()
}
}
</script>
这样您就不会加载整个 lodash 库,甚至不会将整个库保存到
node_modules
。
对于 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)
);
这将返回例如:
aa174375-5b75-4919-acd0-980fcd54003c
我发现的最简单的方法是通过全局 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>
Vue 3.5 具有
useId
可组合项:
<script setup>
import { useId } from "vue";
const inputId = useId();
</script>
<template>
<label for="inputId">Label text</label>
<input id="inputId" type="text" />
</template>
Vue 文档。请参阅Vue Playground。
这似乎对我在 nuxtjs 中使用有用
https://www.npmjs.com/package/uuid
生成的输出示例: 元素:47bfe557-d75f-455c-9a37-85b7935b297b
package.json
"dependencies": {
"uuid": "^8.3.2"
},
在子组件上,可能不是最好的方法,但似乎可行
...
<ComponentName v-if="element" />
...
import { v4 as uuidv4 } from 'uuid';
...
data() {
return {
element: null,
}
}
...
mounted() {
this.element = uuidv4();
}
如果您使用 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>
我在回复中没有看到的一个简单方法是:
<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>
在 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>
这个包似乎是解决跨多个组件的 DOM 中具有非唯一 ID 的根本问题的一个很好的解决方案:
使用组件是一种趋势。组件很酷,它们很小、很明显、易于使用并且是模块化的。直到涉及到 id 属性。
一些 HTML 标签属性需要使用 id 属性,例如 label[for]、input[form] 和许多 aria-* 属性。 id 的问题在于它不是模块化的。如果页面上的多个 id 属性具有相同的值,它们可能会相互影响。
VueUniqIds 可以帮助你摆脱这个问题。它提供了一组与 id 相关的指令,通过添加唯一字符串自动修改值,同时保持属性易于阅读。
Nuxt 3 有可组合项 useId
<script setup lang="ts">
const id = useId()
</script>
<template>
<div>
<label :for="id">Email</label>
<input :id="id" name="email" type="email" />
</div>
</template>
在Vue3中,我们可以使用
getCurrentInstance().uid
来获取uid。
例如我使用 ts & Composition API,所以我的代码是:
<script setup lang="ts">
import { getCurrentInstance } from 'vue'
const id = getCurrentInstance()?.uid
</script>
<template>
<input type="checkbox" :id="`el-${id}`" />
<label :for="`el-${id}`">Label</label>
</template>
如果你的uid没有被其他组件使用,我有一个想法。
uid: Math.random()
简单又足够。
也可以使用这种模式(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>
希望有帮助