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

Vue.js: How to set a unique ID for each component instance?

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

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

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

每个组件都有一个唯一的 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 属性 在实例中不存在,代码将抛出错误,以便您可以更新它以使用自定义或新的唯一 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");
            }
        });
    }
});

关于 Nihat 的观点(以上):Evan You 建议不要使用 _uid:“vm _uid 保留供内部使用,重要的是将其保密(而不是在用户代码中依赖它),以便我们保留为未来潜在用例更改其行为的灵活性。...我建议自己生成 UID [使用模块、全局混合等]"

使用 this GitHub issue 中建议的 mixin 生成 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-unique-id Vue plugin for this on npm.

回答

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

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 属性 即 reserved for internal use.

在你的组件中像这样使用它:

<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

It is a trend to use components. Components are cool, they are small, obvious, easy to use and modular. Untill it comes to the id property.

Some HTML tag attributes requires using an id property, like label[for], input[form] and many of aria-* attributes. And the problem with the id is that it is not modular. If several id properties on the page will has the same value they can affect each other.

VueUniqIds helps you to get rid of this problem. It provides the set of id-related directives which value is automatically modified by adding unique string while keeping the attrbitue easy to read.

npm i -S lodash.uniqueid

然后在你的代码中...

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

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

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

如果您使用的是 TypeScript,没有任何插件,您可以简单地在 class 组件中添加一个静态 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>

这似乎对我有用 https://www.npmjs.com/package/uuid

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

package.json

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

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

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();
}

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

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

npm i uuid

然后,在您的 main.js 文件中创建一个全局混合:

// 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>
  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)
        );

这将 return 例如:

aa174375-5b75-4919-acd0-980fcd54003c