naive-ui
naive-ui copied to clipboard
建议新增验证码输入组件
问题的清晰而简明的描述
验证码输入组件:
接受一个长度参数,指示验证码长度,比如图中是6。
对外暴露一个结果值,以及输入事件、输入完成事件。
每次在输入框中完成输入后会自动focus到下一个输入框,全部输入完之后blur。如果删除一个输入就自动focus到上一个输入框。
建议的解决方案
类似于这样的东西:
<script setup lang="ts">
import { ref, computed, watch, defineEmits, defineProps } from 'vue'
import {
NFlex, NInput
} from 'naive-ui'
import type { InputInst } from 'naive-ui'
interface Props {
length?: number
code?: string
}
interface InputTarget {
key: string
ref: InputInst | null
value: string
}
const props = defineProps<Props>()
const emit = defineEmits(['update:code', 'complete'])
const length = props.length ?? 6
const inputs = ref<InputTarget[]>(Array.from({ length }, (_, index) => ({
key: `input-${index}`,
ref: null,
value: ''
})))
const code = computed(() => inputs.value.map(input => input.value).join(''))
const handleInput = (value: string, index: number) => {
if (value.length === 1 && /^[a-zA-Z0-9]$/.test(value)) {
inputs.value[index].value = value
if (index < length - 1) {
(inputs.value[index + 1].ref as InputInst)?.focus()
} else {
(inputs.value[index].ref as InputInst)?.blur()
emit('complete', code.value)
}
} else if (value === '') {
if (index > 0) {
(inputs.value[index - 1].ref as InputInst)?.focus()
}
} else {
inputs.value[index].value = value.slice(0, 1)
}
}
watch(code, (newCode) => {
emit('update:code', newCode)
})
</script>
<template>
<n-flex justify="space-around">
<n-input v-for="(input, index) in inputs" :key="input.key"
style="text-align: center; font-size: larger; width: 40px;" :maxlength="1" size="large" :show-button="false"
placeholder="" v-model:value="input.value" @input="value => handleInput(value, index)"
:ref="el => inputs[index].ref = el as unknown as InputInst"
:allow-input="value => /^[a-zA-Z0-9]$/.test(value)" />
</n-flex>
</template>
备选方案
No response
附加上下文
No response