5.4 KiB
5.4 KiB
title, description
| title | description |
|---|---|
| SliderCaptcha 滑块验证码 | 按住滑块拖到行内结束端完成验证,支持键盘操作与 RTL |
SliderCaptcha 滑块验证码
SliderCaptcha 是一个「按住滑块拖到最右端」的验证控件,v-model 绑 boolean,true 表示已验证通过。
何时使用
- 登录 / 注册 / 短信验证码等需要「一次人为停顿」的入口;
- 轻量混淆脚本、降低误触强度的场景;
- 不要把它当安全边界:拖拽与键盘都能被脚本模拟,它能挡住的只是「顺手连点」,真正的风控要靠服务端。
基础用法
v-model 绑 boolean;success 在通过的那一刻触发一次,方便埋点或联动下一步。
text / successText 可覆盖语言包文案(默认取 captcha 语言包分组)。
尺寸
size 取 small / medium / large,高度分别跟随 --g3-control-height-sm / --g3-control-height / --g3-control-height-lg;手柄是正方形,宽度自动等于高度。
与表单一起使用
放进 G3FormItem 时,label 与校验交给表单,滑块只负责提供值。验证是有状态的,每轮提交都要复位:清掉绑定值后调 resume(),让用户重新拖一次。
键盘与无障碍
手柄是 role="slider",带 aria-valuemin / aria-valuemax / aria-valuenow(0~100 的完成度)与 aria-valuetext(当前提示文案,通过后是成功文案),读屏可直接播报状态。
| 按键 | 行为 |
|---|---|
Tab |
聚焦手柄(未通过时才可聚焦,通过后 tabindex="-1") |
→ / ↑ |
沿屏幕上「向右」推进一档(行程的 1/10,最少 20px) |
← / ↓ |
回退一档 |
Home |
回到起点(不复位通过状态) |
End |
直达终点并通过验证 |
keyboard={false} 可关掉键盘通道(只保留指针拖拽)。
RTL
位置用逻辑属性 inset-inline-start 表达,镜像由 dir 自动完成:RTL 下手柄从右侧起步、向左拖到终点。指针位移按行内方向折算(useDirection),方向键的左右也随方向翻转 —— 对用户而言始终是「朝屏幕上那个方向推到底」。
API
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue |
boolean |
false |
双向绑定:是否已验证通过 |
text |
string |
语言包 | 未通过时的提示文案 |
successText |
string |
语言包 | 通过后的文案 |
disabled |
boolean |
false |
禁用态:不响应拖拽与键盘(样式不作整体半透明) |
size |
'small' | 'medium' | 'large' |
'medium' |
尺寸 |
keyboard |
boolean |
true |
是否支持键盘操作 |
Events
| 名称 | 参数 | 说明 |
|---|---|---|
update:modelValue |
(value: boolean) |
验证状态变化 |
success |
({ isPassing: true }) |
通过时触发一次 |
start |
(event: PointerEvent) |
开始拖拽 |
move |
({ event, moveDistance, offset }) |
拖拽过程中触发(键盘操作不触发) |
end |
(event: PointerEvent) |
拖拽结束(含取消) |
Slots
| 名称 | 参数 | 说明 |
|---|---|---|
text |
{ isPassing } |
覆盖提示文案 |
action |
{ isPassing } |
覆盖手柄里的图标(默认 ChevronsRight / 通过后 Check,RTL 下由全库的图标镜像规则翻面) |
实例方法
| 名称 | 签名 | 说明 |
|---|---|---|
resume |
() => void |
复位到未通过状态(清绑定值 + 回弹动画),校验失败后调用 |
类型定义
export type SliderCaptchaSize = 'small' | 'medium' | 'large'
export interface SliderCaptchaProps {
modelValue?: boolean
text?: string
successText?: string
disabled?: boolean
size?: SliderCaptchaSize
keyboard?: boolean
}
样式变量
| 变量 | 默认值 | 说明 |
|---|---|---|
--g3-control-height |
32px |
默认高度(手柄宽 = 高度) |
--g3-control-height-sm |
24px |
size="small" 的高度 |
--g3-control-height-lg |
40px |
size="large" 的高度 |
--g3-fill |
rgba(0, 0, 0, 0.04) |
轨道底色 |
--g3-border-color |
#d9d9d9 |
轨道描边 |
--g3-color-success |
hsl(144 57% 58%) |
进度条与通过后的手柄图标色 |
--g3-bg-container |
#fff |
手柄底色 |
实现说明
- 拖拽走 Pointer Events +
setPointerCapture(与bindDrag/bindResize同一套):指针移出组件、触屏、手写笔都能正确收尾,不需要往document上挂全局监听;捕获失败的老环境会退化成「移出即松手」,不会卡住。 - 跟手不加过渡:拖拽期间进度条与手柄必须实时跟随指针,只有回弹 /
Home/End跳转才启用 300ms 过渡(is-returning),否则会有「拖不动」的手感。 - 行程 = 容器宽 - 手柄宽:每次交互开始时量一次
getBoundingClientRect(),因此容器宽度自适应、字体缩放、size变化都不需要监听 resize。 - 只有从「已通过」回退时才
emit('update:modelValue', false):中途松手的回弹不该对外重复报一次false。 - 文案不硬编码:默认值来自语言包
captcha.slide/captcha.verified/captcha.sliderLabel。 - 初始
modelValue = true(回填已通过状态)时,手柄在挂载后一帧落到行程末端,不会停在起点。