代码演示
如何引入
<script setup lang="ts">
import { PinCode } from '@fibrous/semi-ui-vue';
</script>
基本使用
代码
<script setup lang="ts">
import { PinCode } from '@fibrous/semi-ui-vue';
const onComplete = (value: string) => console.log('pincode: ', value);
const onChange = (value: string) => console.log(value);
</script>
<template>
<div>
<PinCode aria-label="Verification code, small" defaultValue="123456" size="small" @change="onChange" @complete="onComplete" />
<br />
<PinCode aria-label="Verification code, default" defaultValue="123456" size="default" @change="onChange" @complete="onComplete" />
<br />
<PinCode aria-label="Verification code, large" defaultValue="123456" size="large" @change="onChange" @complete="onComplete" />
</div>
</template>受控
使用 v-model 绑定验证码字符串
代码
<script setup lang="ts">
import { ref } from 'vue';
import { Button, PinCode } from '@fibrous/semi-ui-vue';
const value = ref('69af41');
const setRandomValue = () => {
value.value = String(Math.floor(Math.random() * 100000000)).slice(0, 6);
};
const onComplete = (code: string) => console.log('pincode: ', code);
const onChange = (code: string) => console.log(code);
</script>
<template>
<div>
<Button @click="setRandomValue">Set Random Value</Button>
<br />
<br />
<PinCode v-model="value" aria-label="Verification code" format="mixed" @change="onChange" @complete="onComplete" />
</div>
</template>限制验证码格式
设置位数
通过 count 设置位数,默认 6 位,下方 Demo 设置为 4 位
代码
<script setup lang="ts">
import { PinCode } from '@fibrous/semi-ui-vue';
const onComplete = (value: string) => console.log('pincode: ', value);
const onChange = (value: string) => console.log(value);
</script>
<template>
<PinCode aria-label="Verification code" :count="4" defaultValue="6688" size="large" @change="onChange" @complete="onComplete" />
</template>设置字符范围
使用 format 控制可输入的字符范围
- 传入 "number" 只允许设置数字
- 传入 "mixed" 允许数字和字母
- 传入正则表达式,只允许输入可通过正则判定的字符
- 传入函数,验证码会在输入的时候以字符为单位被依次作为参数分别单独传入进行校验,当函数返回 true 时,允许该字符被输入进 PinCode
纯数字
字母和数字
只大写字母
只小写字母(函数判断)
字母和数字
只大写字母
只小写字母(函数判断)
代码
<script setup lang="ts">
import { PinCode, Typography } from '@fibrous/semi-ui-vue';
const { Text } = Typography;
const onComplete = (value: string) => console.log('pincode: ', value);
const isLower = (char: string) => /[a-z]/.test(char);
</script>
<template>
<div>
<Text id="pincode-format-number">纯数字</Text>
<PinCode aria-labelledby="pincode-format-number" format="number" @complete="onComplete" />
<br />
<Text id="pincode-format-mixed">字母和数字</Text>
<PinCode aria-labelledby="pincode-format-mixed" format="mixed" @complete="onComplete" />
<br />
<Text id="pincode-format-upper">只大写字母</Text>
<PinCode aria-labelledby="pincode-format-upper" :format="/[A-Z]/" @complete="onComplete" />
<br />
<Text id="pincode-format-lower">只小写字母(函数判断)</Text>
<PinCode aria-labelledby="pincode-format-lower" :format="isLower" @complete="onComplete" />
</div>
</template>手动聚焦失焦
使用模板 ref 上的方法 focus 与 blur,入参为对应 Input 的序号,序号从 0 开始
代码
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue';
import { Button, PinCode, type PinCodeHandle } from '@fibrous/semi-ui-vue';
const value = ref('69af41');
const pinCode = useTemplateRef<PinCodeHandle>('pinCode');
const onComplete = (code: string) => console.log('pincode: ', code);
const onChange = (code: string) => console.log(code);
</script>
<template>
<div>
<Button @click="pinCode?.focus(2)">Focus Third Input</Button>
<br />
<br />
<PinCode ref="pinCode" v-model="value" aria-label="Verification code" format="mixed" @change="onChange" @complete="onComplete" />
</div>
</template>API 参考
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 输入框内容,配合 v-model 使用。 | string | undefined |
| modelModifiers | v-model 修饰符,由 Vue 在使用 v-model.trim 等修饰符时传入;声明后修饰符不再作为属性落到根元素上。 | ModelModifiers | undefined |
| defaultValue | 非受控时的初始内容。 | string | semiGlobalDefault("PinCode", "defaultValue") |
| count | 验证码位数。 | number | semiDefault("PinCode", "count", 6) |
| format | 单个字符的格式限制:number 只允许数字,mixed 允许数字和字母,正则或函数按字符判定。 | PinCodeFormat | undefined |
| autofocus | 挂载时是否自动聚焦到第一个输入框。只在用户明确进入验证码输入步骤时开启,页面加载时自动聚焦会让读屏跳过之前的内容。 | boolean | semiDefault("PinCode", "autofocus", false) |
| disabled | 是否禁用。 | boolean | semiGlobalDefault("PinCode", "disabled") |
| size | 输入框大小,可选 large、default、small。 | Size | semiGlobalDefault("PinCode", "size") |
| validateStatus | 校验状态,传给每个输入框;error 时显示错误样式。 | "default" | "error" | "warning" | "success" | semiGlobalDefault("PinCode", "validateStatus") |
Events
| 事件 | 说明 | 回调参数 |
|---|---|---|
| update:modelValue | 内容变化时触发,供 v-model 回写。 | [value: string] |
| change | 内容变化时触发,参数为当前内容。 | [value: string] |
| complete | 所有位数输入完毕时触发,参数为当前内容。 | [value: string] |
| focus | 焦点进入整个验证码时触发,在输入框之间移动不触发。 | [event: FocusEvent] |
| blur | 焦点离开整个验证码时触发。 | [event: FocusEvent] |
Slots
| 插槽 | 说明 | 作用域参数 |
|---|---|---|
| 无 |
Exposes
| 名称 | 说明 | 类型 |
|---|---|---|
| focus | 聚焦第 index 个输入框,序号从 0 开始,超出范围时忽略;光标放在该格字符之后。 | Type(index: number) => void |
| blur | 让第 index 个输入框失焦,序号从 0 开始,超出范围时忽略。 | Type(index: number) => void |
class、style、aria-label、aria-labelledby、data-* 经 attrs 落在 role="group" 的根元素上。id 落在第一个输入框上,<label for> 指向第一格。aria-describedby、aria-errormessage、aria-invalid、aria-required、tabindex 落在每个输入框上。name、insetLabel、insetLabelId 被丢弃。
通过模板 ref 调用 focus(index) 与 blur(index),序号从 0 开始,超出范围时忽略;focus 之后光标放在该格字符之后。
Accessibility
ARIA
- 根元素为
role="group",名称通过aria-label或aria-labelledby提供;没有可见标签时请传aria-label,否则分组没有名称。 - 每格输入框的可访问名称来自语言包,形如「第 1 位,共 6 位」,随
count与格子序号变化,无需手动设置。 aria-describedby、aria-errormessage、aria-invalid、aria-required落在每个输入框上;validateStatus传给每个输入框。format为"number"时输入框使用数字软键盘(inputmode="numeric"),其余为文本键盘。
键盘和焦点
- 每个格子是独立的输入框,输入一个合法字符后焦点移到下一格,在最后一格输入后失焦;已填内容总是从第一格起连续,在空格子之后输入的字符落在第一个空格子上。
Tab与Shift+Tab在格子之间切换。 左箭头、右箭头在格子之间移动焦点;Backspace与Delete都删除当前格字符,后面的字符依次前移,Backspace还会把焦点移到上一格。- 粘贴整段验证码时,从当前格起按字符依次填入各格,遇到不合法字符即停止。
autoFocus(Vue 为autofocus)只在用户明确进入验证码输入步骤时开启,页面加载时自动聚焦会让读屏跳过之前的内容。