理解 Vue3.5 的 useId 功能

用于为无障碍属性或表单元素生成每个应用内唯一的 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 功能以在异步环境中工作?这个目前还不知道。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值