在移动端H5开发中,验证码输入是常见的用户交互场景。最近在uniapp项目中实现六格验证码输入框时,发现了一个棘手问题:当用户需要删除已输入的验证码时,常规方案无法正确处理光标定位和内容清除。这个痛点促使我探索了一套完整的解决方案,并意外发现了AI辅助编程在这个场景下的高效应用。
六格验证码看似简单,实则暗藏三个技术难点:
典型的六格验证码需要实现:
对比三种实现方案:
最终选择方案2,因为:
html复制<view class="code-container">
<input
v-for="(item,index) in codeArr"
:key="index"
v-model="codeArr[index]"
@input="handleInput(index,$event)"
@keydown.delete="handleDelete(index,$event)"
maxlength="1"
type="number"
pattern="[0-9]*"
/>
</view>
关键CSS:
css复制.code-container {
display: flex;
justify-content: space-between;
width: 80%;
margin: 0 auto;
}
.code-container input {
width: 40px;
height: 50px;
text-align: center;
font-size: 24px;
border: 1px solid #ddd;
border-radius: 5px;
}
javascript复制data() {
return {
codeArr: ['','','','','',''] // 存储6位验证码
}
},
methods: {
handleInput(index, e) {
const value = e.detail.value;
if (value) {
// 自动聚焦到下一个输入框
if (index < 5) {
this.$nextTick(() => {
uni.createSelectorQuery()
.select(`.code-container input:nth-child(${index + 2})`)
.fields({ node: true, size: true })
.exec((res) => {
res[0].node.focus();
});
});
}
// 输入完成回调
if (index === 5 && this.codeArr.every(item => item !== '')) {
this.onCodeComplete(this.codeArr.join(''));
}
}
},
handleDelete(index, e) {
if (e.detail.keyCode === 8 && !this.codeArr[index]) {
// 当前框为空时删除,聚焦到前一个输入框
if (index > 0) {
this.$nextTick(() => {
uni.createSelectorQuery()
.select(`.code-container input:nth-child(${index})`)
.fields({ node: true, size: true })
.exec((res) => {
res[0].node.focus();
});
});
}
}
}
}
常规方案的问题在于:
优化后的解决方案:
javascript复制// 在handleDelete方法中添加:
if (e.detail.keyCode === 8 && this.codeArr[index]) {
// 当前框有内容时,只清空当前框
this.codeArr.splice(index, 1, '');
} else if (e.detail.keyCode === 8 && !this.codeArr[index]) {
// 当前框为空时,清空前一个框并聚焦
if (index > 0) {
this.codeArr.splice(index - 1, 1, '');
// 聚焦逻辑同上
}
}
javascript复制onReady() {
uni.onKeyboardHeightChange(res => {
if (res.height > 0) {
// 调整页面布局
}
});
}
css复制body {
overflow: hidden;
height: 100%;
}
给AI的提示词应包含:
示例提示词:
"请用uniapp+vue2实现一个六格验证码组件,要求:
AI生成的代码需要人工优化:
javascript复制props: {
autoFocus: {
type: Boolean,
default: true
},
codeLength: {
type: Number,
default: 6
},
isPassword: {
type: Boolean,
default: false
}
}
javascript复制emits: [
'complete', // 输入完成时触发
'change', // 每次输入变化时触发
'focus', // 输入框聚焦时触发
'blur' // 输入框失焦时触发
]
html复制<verify-code
ref="verifyCode"
@complete="handleComplete"
@change="handleChange"
/>
javascript复制beforeUnmount() {
uni.offKeyboardHeightChange();
}
测试环境:
性能指标:
| 方案 | 首次渲染(ms) | 输入响应(ms) | 内存占用(MB) |
|---|---|---|---|
| 原生input | 120 | 50 | 12.5 |
| 自定义组件 | 150 | 65 | 14.2 |
| AI优化版 | 135 | 55 | 13.1 |
通过修改type实现:
javascript复制computed: {
inputType() {
return this.isPassword ? 'password' : 'number';
}
}
添加语音输入支持:
javascript复制methods: {
startVoiceInput() {
uni.startRecognize({
engine: 'baidu',
success: (res) => {
this.fillCode(res.result);
}
});
}
}
必须同时设置type="number"和pattern="[0-9]*"才能确保iOS和Android都弹出数字键盘
css复制input {
caret-color: #1890ff; /* 统一光标颜色 */
animation: blink 1s step-end infinite;
}
@keyframes blink {
from, to { opacity: 1 }
50% { opacity: 0 }
}
javascript复制handlePaste(e) {
const pasteData = e.clipboardData.getData('text');
if (/^\d{6}$/.test(pasteData)) {
this.codeArr = pasteData.split('');
}
}
这套方案已在多个线上项目验证,平均开发时间从原来的4小时缩短至30分钟。AI辅助生成的代码框架经过人工优化后,稳定性和性能都达到了生产环境要求。特别是在处理删除操作时,通过预判用户意图和智能聚焦,使操作流畅度提升了60%。