InputOtp
概述
基于真实原生 input 的一次性密码(OTP / 验证码)输入组件。它保留了 vue-input-otp 中成熟的选区、粘贴、移动端自动填充与密码管理器适配行为,同时提供 VeanUI 默认样式和可完全自定义的 scoped slot。适用于短信验证码、邮箱验证码、双因素认证等任意定长验证码输入场景。
用法
特性
- 📏 6 种尺寸:xs、sm、md、lg、xl、2xl
- 🔤 真实原生 input 透明叠加——原生选区、粘贴、移动端自动填充/密码管理器行为
- 📐
align对齐:start / center / end - 🎨 每个字符可完全自定义的
default插槽,支持占位字符与 fake caret - 🔢
maxlength截断 +pattern校验(beforeinput拦截 + 回滚双层防护) - 📋
pasteTransformer归一化粘贴内容,填满时触发complete事件 - 🔐 密码管理器 badge 检测(可用
pushPasswordManagerStrategy关闭) - ♿ 完整无障碍支持——
aria-label、inputmode、axe 零违规
演示
基础
Value: -
占位
自定义插槽
API
Aria 层
5InputOtp
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 根类。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
align | Align | — | 对齐。 |
ui | Partial<InputOtpUi> | — | 该组件的按槽类重写。 |
id | string | — | 原生输入元素的 ID。 |
autocomplete | string | — | 将自动完成提示传递给原生输入控件。 |
autofocus | boolean | — | 输入是否应聚焦于挂载。 |
disabled | boolean | — | 输入项是否已被禁用。 |
minlength | number | — | 转发至原生输入的最小长度。 |
placeholder | string | — | 视觉插槽中使用的占位符字符。 |
readonly | boolean | — | 输入是否为只读。 |
ariaLabel | string | — | 无障碍标签已转发至原生输入。 |
modelValue | string | — | OTP 输入的受控值。 |
defaultValue | string | — | OTP 输入的未受控默认值。 |
maxlength | number | — | OTP 槽位数量。 |
inputmode | InputOtpInputMode | — | 移动设备的虚拟键盘模式。 |
pattern | string | RegExp | — | 用于验证整个 OTP 值的模式。 |
pushPasswordManagerStrategy | InputOtpPushPasswordManagerStrategy | — | 用于避免密码管理器徽章重叠的策略。 |
pasteTransformer | ((pasted: string) => string) | — | 在插入粘贴的内容之前对其进行转换。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | string | 当模型值发生变化时触发。 |
complete | string | 在处理完成时触发。 |
input | string | 在输入发生时生成。 |
change | Event | 在发生变更时触发。 |
select | Event | 在发生 select 事件时触发。 |
focus | FocusEvent | 当焦点发生时触发。 |
blur | FocusEvent | 在焦点移开时触发。 |
mouseover | MouseEvent | 在鼠标悬停时触发。 |
mouseleave | MouseEvent | 在发生 mouseleave 事件时触发。 |
paste | ClipboardEvent | 在发生粘贴操作时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | InputOtpRootSlotProps | 默认插槽的自定义内容。 |
InputOtpCompact
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | string | — | 原生输入元素的 ID。 |
autocomplete | string | — | 将自动完成提示传递给原生输入控件。 |
autofocus | boolean | — | 输入是否应聚焦于挂载。 |
disabled | boolean | — | 输入项是否已被禁用。 |
minlength | number | — | 转发至原生输入的最小长度。 |
placeholder | string | — | 视觉插槽中使用的占位符字符。 |
readonly | boolean | — | 输入是否为只读。 |
ariaLabel | string | — | 无障碍标签已转发至原生输入。 |
modelValue | string | — | OTP 输入的受控值。 |
defaultValue | string | — | OTP 输入的未受控默认值。 |
maxlength | number | — | OTP 槽位数量。 |
inputmode | InputOtpInputMode | — | 移动设备的虚拟键盘模式。 |
pattern | string | RegExp | — | 用于验证整个 OTP 值的模式。 |
pushPasswordManagerStrategy | InputOtpPushPasswordManagerStrategy | — | 用于避免密码管理器徽章重叠的策略。 |
pasteTransformer | ((pasted: string) => string) | — | 在插入粘贴的内容之前对其进行转换。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | string | 当模型值发生变化时触发。 |
complete | string | 在处理完成时触发。 |
input | string | 在输入发生时生成。 |
change | Event | 在发生变更时触发。 |
select | Event | 在发生 select 事件时触发。 |
focus | FocusEvent | 当焦点发生时触发。 |
blur | FocusEvent | 在焦点移开时触发。 |
mouseover | MouseEvent | 在鼠标悬停时触发。 |
mouseleave | MouseEvent | 在发生 mouseleave 事件时触发。 |
paste | ClipboardEvent | 在发生粘贴操作时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | InputOtpRootSlotProps | 默认插槽的自定义内容。 |
InputOtpInput
InputOtpPositioner
InputOtpRoot
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | string | — | 原生输入元素的 ID。 |
autocomplete | string | — | 将自动完成提示传递给原生输入控件。 |
autofocus | boolean | — | 输入是否应聚焦于挂载。 |
disabled | boolean | — | 输入项是否已被禁用。 |
minlength | number | — | 转发至原生输入的最小长度。 |
placeholder | string | — | 视觉插槽中使用的占位符字符。 |
readonly | boolean | — | 输入是否为只读。 |
ariaLabel | string | — | 无障碍标签已转发至原生输入。 |
modelValue | string | — | OTP 输入的受控值。 |
defaultValue | string | — | OTP 输入的未受控默认值。 |
maxlength | number | — | OTP 槽位数量。 |
inputmode | InputOtpInputMode | — | 移动设备的虚拟键盘模式。 |
pattern | string | RegExp | — | 用于验证整个 OTP 值的模式。 |
pushPasswordManagerStrategy | InputOtpPushPasswordManagerStrategy | — | 用于避免密码管理器徽章重叠的策略。 |
pasteTransformer | ((pasted: string) => string) | — | 在插入粘贴的内容之前对其进行转换。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | string | 当模型值发生变化时触发。 |
complete | string | 在处理完成时触发。 |
input | string | 在输入发生时生成。 |
change | Event | 在发生变更时触发。 |
select | Event | 在发生 select 事件时触发。 |
focus | FocusEvent | 当焦点发生时触发。 |
blur | FocusEvent | 在焦点移开时触发。 |
mouseover | MouseEvent | 在鼠标悬停时触发。 |
mouseleave | MouseEvent | 在发生 mouseleave 事件时触发。 |
paste | ClipboardEvent | 在发生粘贴操作时触发。 |
注意事项
架构与对标差异
VeanUI 将 input-otp 拆分为负责透明输入叠加、选区镜像与校验的 Aria 层(@vean/aria/input-otp),以及负责变体与 UnoCSS 样式的 styled 层(@vean/ui)。Aria InputOtpCompact 组合 InputOtpRoot / InputOtpPositioner / InputOtpInput。这是 reka-ui 与 shadcn 所用 vue-input-otp 方案的移植,尺寸变体与 align 三态为 VeanUI 的差异化增强。
| 能力 | VeanUI | reka-ui InputOtp | shadcn InputOTP | Element Plus |
|---|---|---|---|---|
| Aria/styled 分离 | ✅ | — | — | — |
| 受控/非受控 | ✅ | ✅ | ✅ | — |
maxlength / pattern | ✅ | ✅ | ✅ | — |
| 真实 input 透明叠加 | ✅ | ✅ | ✅ | — |
| 选区镜像 | ✅ | ✅ | ✅ | — |
| 粘贴转换 | ✅ | ✅ | ✅ | — |
| 密码管理器 badge 适配 | ✅ | ✅ | ✅ | — |
| iOS 自动填充 | ✅ | ✅ | ✅ | — |
complete 事件 | ✅ | ✅ | ✅ | — |
| 尺寸变体(xs…2xl) | ✅ | — | — | — |
align 三态 | ✅ | ✅ | ✅ | — |
| 自定义视觉槽(fake caret) | ✅ | ✅ | ✅ | — |
注意事项
maxlength为必填——它决定渲染的字符个数。aria-label属性以ariaLabel(camelCase)声明;kebab-case 属性与 camelCase prop 均可生效,未传入时回退本地化默认文案「One-time password」。- locale 化默认
aria-label与contextmenu处理列为增强待办。
常见问题
如何自定义字符格子?
使用 default 插槽。每个字符会获得 char、placeholderChar、isActive、hasFakeCaret,可自由渲染方框、分隔符或自定义光标。
如何在校验码填满后触发动作?
监听 complete 事件,它会在所有格子填满时触发一次。
如何限制可输入的字符?
maxlength 控制长度,pattern 提供逐字符校验正则。非法输入会被 beforeinput 拦截,并在 input 时回滚。
如何让 OTP 参与原生表单?
传入 name——透明 input 携带值并参与原生表单提交与自动填充。