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

Pie*_*reB 89 vue.js

我想创建一个包含标签和输入的Vue.js组件.例如 :

<label for="inputId">Label text</label>
<input id="inputId" type="text" />
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

zxz*_*zak 147

每个组件都有一个唯一的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>
Run Code Online (Sandbox Code Playgroud)

如果您想要更多地控制ID,例如,可以在父组件中生成它们.

  • 不要使用`_uid`,它"*[保留供内部使用,保持私有(并且不依赖于用户代码)非常重要,这样我们就可以灵活地改变其行为,以备将来的用例使用] (https://github.com/vuejs/vue/issues/5886#issuecomment-308625735)*". (12认同)
  • 不幸的是,这在TypeScript中不起作用,因为`this._uid`无效.相反,自己生成你的id,例如`public id = uuid4();`,参见[uuid4](/sf/answers/148226641/). (2认同)
  • 当我尝试从Mounted()方法访问它时,我必须将初始化放在beforeMount()方法中,以确保在DOM中设置了ID。 (2认同)
  • 在 vue3 中不起作用 =&gt; 使用下面 __buckthorn__ 的答案 (2认同)

buc*_*orn 26

至于Nihat的观点(上图):Evan You建议不要使用_uid:"vm _uid保留供内部使用,保持私有(并且不依赖于用户代码)非常重要,这样我们就可以灵活地改变它潜在的未来用例的行为....我建议你自己生成UID [使用模块,全局混合等]

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

let uuid = 0;

export default {
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
};
Run Code Online (Sandbox Code Playgroud)

  • 这是 Evan 建议不要使用 _id 的 GitHub 问题:https://github.com/vuejs/vue/issues/5886#issuecomment-308625735 (3认同)
  • this.uuid = crypto.randomUUID(); (2认同)

Nih*_*hat 19

虽然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");
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 是的,但如果已发布的 api 发生更改/删除,他们只需更改整个代码中的一处即可。在另一个答案中,它是每个组件的。我已经在标题中强调了这一点。 (3认同)
  • 这仍然使用 uid,在您自己的回答中承认不建议这样做。请不要发布提倡不良做法的答案。这个答案应该被删除。 (2认同)

hol*_*x_x 14

对于 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)
        );
Run Code Online (Sandbox Code Playgroud)

这将返回例如:

aa174375-5b75-4919-acd0-980fcd54003c


m.e*_*roy 8

npm i -S lodash.uniqueid
Run Code Online (Sandbox Code Playgroud)

然后在你的代码...

npm i -S lodash.uniqueid
Run Code Online (Sandbox Code Playgroud)

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


ber*_*nie 6

更新资料

在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;
  };
});
Run Code Online (Sandbox Code Playgroud)

这不依赖保留供内部使用的内部_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" />
Run Code Online (Sandbox Code Playgroud)

要产生这样的东西:

<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" />
Run Code Online (Sandbox Code Playgroud)

  • 请注意,该插件似乎不适用于 Vue3 (2认同)
  • “uuid”是一个不幸的名称选择,因此我将其重命名为“uidCounter”。JavaScript 是单线程的,所以我看不出上面的代码中可能会出现哪些竞争条件。`uidCounter` 是自动读取和更新的,因为没有其他线程并且执行不会被抢占。在我看来,对于这个用例来说,实际的 UUID 并没有比简单的递增计数器提供任何好处,但它确实有效。 (2认同)

get*_*kin 5

uuid package我发现的最简单的方法是通过全局 mixin 手动创建 UUID ( )。这样,您就不会依赖任何可能在将来发生更改或被弃用的内容,例如this._uid.

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

npm i uuid
Run Code Online (Sandbox Code Playgroud)

然后,在您的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');
Run Code Online (Sandbox Code Playgroud)

以下是如何在组件中使用它:

<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>
Run Code Online (Sandbox Code Playgroud)