Skip to content

HardcoreInput 硬核输入框

输入框校验器的终极形态。通过 Web Audio API 动态合成 8-bit 复古电子音效(零音频依赖),同时在校验结果变化时触发 Neobrutalist 表情弹跳与物理震动。

预览

Preview

基础用法(Blur 校验)

多规则校验(Input 实时校验)

禁用音效

关闭抖动 (shakeOnError=false)

只读状态 (readonly)

安装

pnpm dlx brutx-vue@latest add hardcore-input

用法

vue
<script setup>
import { ref } from 'vue'
import { HardcoreInput } from 'brutx-ui-vue'

const value = ref('')

const minLength = (val) => val.length >= 5 || '至少需要 5 个字符'
const hasNumber = (val) => /\d/.test(val) || '必须包含数字'
</script>

<template>
    <HardcoreInput
        v-model="value"
        placeholder="输入内容..."
        :rules="[minLength, hasNumber]"
        validate-on="blur"
    />
</template>

校验触发时机

模式说明
blur失焦时校验(默认)
input每次输入时实时校验
submit外部调用 validate() 时校验

音效系统

通过 useAudioEngine composable 使用 Web Audio API 合成三种音效:

音效波形说明
typeTriangle打字音效,带 50ms 节流
successSine校验通过,频率上升
failSquare校验失败,频率下降

可通过 sound prop 禁用音效。

视觉反馈

  • 成功:输入框边框变为 --brutal-success 色,右侧显示酷表情 SVG
  • 错误:输入框边框变为 --brutal-destructive 色,右侧显示怒气表情 SVG,输入框产生抖动动画
  • 默认:无额外反馈

Form 集成

HardcoreInput 可与 Form 系统集成,当存在于 FormField 中时自动同步校验状态:

vue
<Form v-slot="{ handleSubmit }">
    <FormField v-slot="{ componentField }" name="username">
        <FormItem>
            <FormLabel>用户名</FormLabel>
            <HardcoreInput v-bind="componentField" :rules="[minLength]" />
            <FormMessage />
        </FormItem>
    </FormField>
</Form>

组合式函数

useFormFieldValidation

HardcoreInput 内部的校验状态机已抽取为独立的 useFormFieldValidation 组合式函数,可在任何自定义表单控件中复用同一套校验逻辑(规则求值、状态机切换、错误消息管理、触发时机控制)。它不依赖 vee-validate,适合无法接入 Form 系统或需要轻量内联校验的场景。

ts
import { useFormFieldValidation } from 'brutx-ui-vue'
import type { UseFormFieldValidationOptions, ValidationRule, ValidateOn } from 'brutx-ui-vue'

// 校验规则:返回 true 表示通过,返回字符串表示错误消息
const minLength: ValidationRule<string> = (val) => val.length >= 5 || '至少需要 5 个字符'
const hasNumber: ValidationRule<string> = (val) => /\d/.test(val) || '必须包含数字'

const {
    validationState,        // 当前校验状态
    errorMessage,           // 当前错误消息
    validate,               // 主动校验
    reset,                  // 重置为默认状态
    shouldValidateOnInput,  // 是否在 input 时机校验
    shouldValidateOnBlur,   // 是否在 blur 时机校验
} = useFormFieldValidation({
    rules: [minLength, hasNumber],
    validateOn: 'blur',
    defaultErrorMessage: '校验失败',
    onValidationChange: (state, message) => {
        // 状态变化回调,可用于联动音效、震动等副作用
    },
})

UseFormFieldValidationOptions

属性类型默认值说明
rulesMaybeRefOrGetter<ValidationRule<TValue>[]>[]校验规则数组;为空时 validate 永远返回 true 并将状态置为 default
validateOnMaybeRefOrGetter<'input' | 'blur' | 'submit'>'submit'校验触发时机(仅影响 shouldValidateOnInput / shouldValidateOnBlur 的判定,需调用方自行在对应事件中调用 validate
defaultErrorMessageMaybeRefOrGetter<string>'Invalid value'规则返回 false 时的默认错误消息
onValidationChange(state: ValidationState, message?: string) => void校验状态变化时回调(仅在状态实际变化时触发,避免重复)

返回值

属性类型说明
validationStateRef<'default' | 'success' | 'error'>当前校验状态(响应式)
errorMessageRef<string>当前错误消息(响应式,无错误时为空字符串)
validate(value)(value: TValue) => boolean对给定值执行校验;通过返回 true,失败返回 false 并写入 errorMessage
reset()() => void重置为 default 状态并清空错误消息
shouldValidateOnInput()() => boolean是否配置为在 input 时机校验
shouldValidateOnBlur()() => boolean是否配置为在 blur 时机校验

ValidationRule

ts
type ValidationRule<TValue> = (value: TValue) => boolean | string

规则函数接收当前值,返回 true 表示通过,返回 string 表示失败并以该字符串作为错误消息,返回 false 表示失败并使用 defaultErrorMessage

使用示例

在自定义输入控件中复用同一套校验逻辑:

vue
<script setup lang="ts">
import { ref } from 'vue'
import { useFormFieldValidation } from 'brutx-ui-vue'

const value = ref('')
const { validationState, errorMessage, validate, shouldValidateOnBlur } = useFormFieldValidation({
    rules: [(v) => v.length >= 3 || '至少 3 个字符'],
    validateOn: 'blur',
})

function onBlur() {
    if (shouldValidateOnBlur()) validate(value.value)
}
</script>

<template>
    <input
        v-model="value"
        @blur="onBlur"
        :aria-invalid="validationState === 'error'"
        :class="{
            'border-brutal-success': validationState === 'success',
            'border-brutal-destructive': validationState === 'error',
        }"
    />
    <p v-if="errorMessage" class="text-brutal-destructive text-sm">{{ errorMessage }}</p>
</template>

提示:useFormFieldValidation 不绑定具体控件,所有时机判断(shouldValidateOnInput / shouldValidateOnBlur)只返回布尔值,由调用方决定在哪个事件中调用 validatesubmit 时机需调用方在外部(如表单提交时)显式调用 validate

程序化控制

名称说明
validate()主动触发校验
validationState当前校验状态
errorMessage当前错误消息

Props

属性类型默认值说明
modelValuestringundefinedv-model 绑定值
soundbooleantrue是否启用 8-bit 复古电子音效
rulesArray<(val: string) => boolean | string>[]校验规则函数列表
shakeOnErrorbooleantrue输入错误时是否触发输入框抖动
typestring'text'HTML input type 属性
placeholderstringundefined占位文本
disabledbooleanfalse是否禁用
readonlybooleanfalse是否只读
validateOn'input' | 'blur' | 'submit''blur'校验触发时机
classstringundefined外部类覆盖

事件

事件参数说明
@update:modelValue(value: string)v-model 更新事件
@validation-change(state: ValidationState, message?: string)校验状态变化事件,仅在状态实际变化时触发

插槽

插槽作用域说明
default输入框右侧附加内容(如图标、表情区域覆盖)

可访问性

  • 输入框设置了 :aria-invalid:aria-describedby
  • 错误消息设置了 aria-live="polite"
  • 当用户偏好 prefers-reduced-motion: reduce 时,抖动和弹跳动画被禁用

蛮力铸就。