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

问题描述 投票:0回答:18
vue.js uniqueidentifier
18个回答
239
投票

每个组件都有一个唯一的 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,您可以在父组件内生成它们。


77
投票

对于尼哈特的观点(上):

Evan You 建议不要使用 _uid:

vm _uid 保留供内部使用,保持其私有(并且不要在用户代码中依赖它)非常重要,这样我们就可以灵活地更改其行为以适应未来潜在的用例。 ...我建议自己生成 UID [使用模块、全局 mixin 等]

使用此 GitHub 问题中建议的 mixin 来生成 UID 似乎是更好的方法:

let uuid = 0;

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

22
投票

更新

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

20
投票

更新: 如果实例中不存在

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

16
投票
npm i -S lodash.uniqueid

然后在你的代码中...

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

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

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

node_modules


15
投票

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


6
投票

我发现的最简单的方法是通过全局 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>

5
投票

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


4
投票

这似乎对我在 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();
}

2
投票

如果您使用 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>

2
投票

我在回复中没有看到的一个简单方法是:

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

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>

1
投票

这个包似乎是解决跨多个组件的 DOM 中具有非唯一 ID 的根本问题的一个很好的解决方案:

vue-uniq-ids

使用组件是一种趋势。组件很酷,它们很小、很明显、易于使用并且是模块化的。直到涉及到 id 属性。

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

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


0
投票

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>

0
投票

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

-2
投票

根据 MDN,您可以创建隐式 label 绑定。

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

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


-8
投票

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

uid: Math.random()

简单又足够。


-11
投票

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

希望有帮助

© www.soinside.com 2019 - 2024. All rights reserved.