📖 概述
useId()
是 Vue 3 中的一个组合式 API 函数,用于生成唯一的标识符。它确保在服务端渲染(SSR)和客户端渲染之间生成一致的 ID,避免水合不匹配的问题。
🎯 基本概念
什么是 useId?
useId()
返回一个唯一的字符串标识符,该标识符在组件的整个生命周期内保持不变,并且在服务端和客户端之间保持一致。
使用场景
- 🏷️ 为表单元素生成唯一 ID
- 🔗 关联 label 和 input 元素
- 🎯 为 ARIA 属性提供唯一标识
- 🔍 为测试提供稳定的选择器
🔧 函数签名
function useId(): string;
💻 代码示例
🚀 基础用法
<script setup lang="ts">
import { useId } from "vue";
// 生成唯一标识符
const id = useId();
console.log(id); // 例如: "v-1a2b3c4d"
</script>
<template>
<div>
<label :for="id">用户名</label>
<input :id="id" type="text" />
</div>
</template>
🏷️ 表单元素关联
<script setup lang="ts">
import { useId } from "vue";
const inputId = useId();
const checkboxId = useId();
</script>
<template>
<div class="form-group">
<label :for="inputId">邮箱地址</label>
<input :id="inputId" type="email" placeholder="请输入邮箱" />
<div class="checkbox-group">
<input :id="checkboxId" type="checkbox" />
<label :for="checkboxId">订阅新闻</label>
</div>
</div>
</template>
🎯 ARIA 属性支持
<script setup lang="ts">
import { useId } from "vue";
const dialogId = useId();
const descriptionId = useId();
</script>
<template>
<div
role="dialog"
:aria-labelledby="dialogId"
:aria-describedby="descriptionId"
>
<h2 :id="dialogId">确认删除</h2>
<p :id="descriptionId">此操作不可撤销,请确认是否继续。</p>
<button @click="confirm">确认</button>
<button @click="cancel">取消</button>
</div>
</template>
🔍 多个组件实例
<script setup lang="ts">
import { useId } from "vue";
// 每个组件实例都会生成不同的 ID
const containerId = useId();
const listId = useId();
</script>
<template>
<div :id="containerId" class="dropdown">
<button :aria-expanded="isOpen" :aria-controls="listId">选择选项</button>
<ul :id="listId" role="listbox" v-show="isOpen">
<li role="option" v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
⚖️ 与其他 ID 生成方式的对比
❌ 不推荐的方式
<script setup lang="ts">
// 使用 Math.random() - 服务端和客户端不一致
const randomId = Math.random().toString(36).substr(2, 9);
// 使用 Date.now() - 可能导致重复
const timestampId = Date.now().toString();
</script>
✅ 推荐使用 useId
<script setup lang="ts">
import { useId } from "vue";
// 使用 useId - 服务端和客户端一致
const stableId = useId();
</script>
⚠️ 注意事项
🔢 ID 唯一性
useId()
生成的 ID 在同一个组件实例中是唯一的,但在不同的组件实例中会不同:
<script setup lang="ts">
import { useId } from "vue";
const id1 = useId(); // 第一个组件实例的 ID
const id2 = useId(); // 第二个组件实例的 ID
// id1 !== id2
</script>
📝 SSR 兼容性
useId()
确保在服务端渲染和客户端水合时生成相同的 ID:
<script setup lang="ts">
import { useId } from "vue";
const id = useId();
// 在服务端和客户端都会生成相同的 ID
// 避免了水合不匹配的问题
</script>
🛡️ 使用限制
useId()
只能在组件的 setup 函数或<script setup>
中使用:
<script setup lang="ts">
import { useId } from "vue";
// ✅ 正确:在 setup 中使用
const id = useId();
// ❌ 错误:不能在事件处理函数中使用
const handleClick = () => {
const newId = useId(); // 这会导致错误
};
</script>
🎯 最佳实践
1️⃣ 为表单元素生成 ID
<script setup lang="ts">
import { useId } from "vue";
const inputId = useId();
const textareaId = useId();
const selectId = useId();
</script>
<template>
<form>
<div class="form-field">
<label :for="inputId">姓名</label>
<input :id="inputId" type="text" />
</div>
<div class="form-field">
<label :for="textareaId">描述</label>
<textarea :id="textareaId"></textarea>
</div>
<div class="form-field">
<label :for="selectId">城市</label>
<select :id="selectId">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
</div>
</form>
</template>
2️⃣ 组合多个 useId
<script setup lang="ts">
import { useId } from "vue";
const baseId = useId();
const inputId = `${baseId}-input`;
const labelId = `${baseId}-label`;
const errorId = `${baseId}-error`;
</script>
<template>
<div class="form-control">
<label :id="labelId" :for="inputId">密码</label>
<input
:id="inputId"
:aria-labelledby="labelId"
:aria-describedby="errorId"
type="password"
/>
<span :id="errorId" class="error-message"> 密码长度至少6位 </span>
</div>
</template>
3️⃣ 在可复用组件中使用
<script setup lang="ts">
import { useId } from "vue";
interface Props {
label?: string;
error?: string;
}
const props = defineProps<Props>();
const inputId = useId();
const errorId = useId();
</script>
<template>
<div class="input-wrapper">
<label v-if="label" :for="inputId">{{ label }}</label>
<input :id="inputId" :aria-describedby="errorId" v-bind="$attrs" />
<span v-if="error" :id="errorId" class="error">
{{ error }}
</span>
</div>
</template>
❓ 常见问题
Q: useId 生成的 ID 格式是什么?
A:
useId()
生成的 ID 格式类似"v-1a2b3c4d"
,以 “v-” 开头,后跟随机字符串。
Q: 可以在条件渲染中使用 useId 吗?
A: 可以,但要注意 ID 在组件的整个生命周期内保持不变,即使元素被条件渲染。
Q: useId 和 ref 有什么区别?
A:
useId()
用于生成唯一标识符,ref()
用于创建响应式引用。它们的用途完全不同。
📝 总结
useId()
是 Vue 3 中处理唯一标识符的标准方式,特别适用于表单元素、ARIA 属性和 SSR 场景。它确保了服务端和客户端之间的一致性,避免了水合不匹配的问题。在需要唯一 ID 的场景中,始终优先使用useId()
而不是其他随机生成方式。
原文链接:https://code.ifrontend.net/archives/1097,转载请注明出处。
评论0