用于为无障碍属性或表单元素生成每个应用内唯一的 ID。
类型
function useId(): string
示例
<script setup>import { useId } from 'vue'
const id = useId()</script>
<template> <form> <label :for="id">Name:</label> <input :id="id" type="text" /> </form></template>
详细信息:https://github.com/vuejs/rfcs/issues/556
useId() 生成的每个 ID 在每个应用内都是唯一的。它可以用于为表单元素和无障碍属性生成 ID。在同一个组件中多次调用会生成不同的 ID;同一个组件的多个实例调用 useId() 也会生成不同的 ID。
useId() 生成的 ID 在服务器端和客户端渲染之间是稳定的,因此可以安全地在 SSR 应用中使用,不会导致激活不匹配。
如果同一页面上有多个 Vue 应用实例,可以通过 app.config.idPrefix 为每个应用提供一个 ID 前缀,以避免 ID 冲突。
useId 的实现原理并不复杂,它通过访问 Vue 实例的 ids 属性来生成 ID。这个属性是一个数组,包含了用于生成ID的前缀和自增数字。每次调用 useId 时,都会取出当前的数字值,然后进行自增操作,从而确保每次生成的ID都是唯一的。
实现的源码:packages/runtime-core/src/helpers/useId.ts
export function useId(): string { const i = getCurrentInstance() if (i) { return (i.appContext.config.idPrefix || 'v') + '-' + i.ids[0] + i.ids[1]++ } else if (__DEV__) { warn( `useId() is called when there is no active component ` + `instance to be associated with.`, ) } return ''}
注意,在异步上下文使用 useId(例如 setTimeout、setInterval 或 Promise 回调)中调用时无法按预期运行。这是因为当前实现依赖于getCurrentInstance(),在这些情况下会返回 null。
这是一个简单的例子来说明这个问题:
<script setup>import { ref, onMounted } from 'vue'import { useId } from 'vue'
const message = ref('')
onMounted(() => { const id = useId() // 正常用法 message.value = `Initial ID: ${id}`
setTimeout(() => { const asyncId = useId() // 错误用法 message.value = `Async ID: ${asyncId}` // asyncId is undefined }, 1000)})</script>
<template> <div>{{ message }}</div></template>
关于这个问题已经有用户在 Github 中反馈了。https://github.com/vuejs/core/pull/11404 是否有计划在未来版本中扩展 useId 功能以在异步环境中工作?这个目前还不知道。