本文转载于:猿2048网站⇨https://www.mk2048.com/blog/blog.php?id=hc0c1iiccb
效果
先来看波完成效果图

需求
输入4位或6位短信验证码,输入完成后收起键盘
实现步骤
第一步
布局排版
<div class="security-code-wrap"> <label for="code"> <ul class="security-code-container"> <li class="field-wrap" v-for="(item, index) in number" :key="index"> <i class="char-field">{{value[index] || placeholder}}</i> </li> </ul> </label> <input ref="input" class="input-code" @keyup="handleInput($event)" v-model="value" id="code" name="code" type="tel" :maxlength="number" autocorrect="off" autocomplete="off" autocapitalize="off"> </div>
- 使用li元素来模拟输入框的显示,没有别的目的,就只是为了语义化,当然你也可以使用其他任意一个元素来模拟,比如div。
- 使用label标签的好处在于它可以跟input的click事件关联上,一方面实现了语义化解决方案,另一方面也省去了我们通过js来唤起虚拟键盘。
隐藏输入框
.input-code { position: absolute; left: -9999px; top: -9999px; }
- 将真实的输入框定位到屏幕可视区域以外的地方,虚拟键盘被唤起时,就不会将页面往上顶了。所以你的验证码输入组件一定要放在虚拟键盘遮挡不了的地方。
第二步
处理验证码输入
handleSubmit () { this.$emit('input', this.value) }, handleInput (e) { if (e.target.value.length >= this.length) { this.hideKeyboard() } this.handleSubmit() }
- 输入时,给输入框赋一次值,是为了解决android端上输入框失焦后重新聚焦,输入光标会定在第一位的前面,经过赋值再聚焦,光标的位置就会显示在最后一位后面。
第三步
完成输入后关闭虚拟键盘
hideKeyboard() { // 输入完成隐藏键盘 document.activeElement.blur() // ios隐藏键盘 this.$refs.input.blur() // android隐藏键盘 }
组件完整代码
<template> <div class="security-code-wrap"> <label :for="`code-${uuid}`"> <ul :class="`${theme}-container security-code-container`"> <li class="field-wrap" v-for="(item, index) in length" :key="index"> <i class="char-field">{{value[index] || placeholder}}</i> </li> </ul> </label> <input ref="input" class="input-code" @keyup="handleInput($event)" v-model="value" :id="`code-${uuid}`" :name="`code-${uuid}`" type="tel" :maxlength="length" autocorrect="off" autocomplete="off" autocapitalize="off"> </div> </template> <script> export default { name: 'SecurityCode', // component properties props: { length: { type: Number, default: 4 }, placeholder: { type: String, default: '-' }, theme: { type: String, default: 'block' } }, // variables data () { return { value: '' } }, computed: { uuid () { return Math.random().toString(36).substring(3, 8) } }, methods: { hideKeyboard () { // 输入完成隐藏键盘 document.activeElement.blur() // ios隐藏键盘 this.$refs.input.blur() // android隐藏键盘 }, handleSubmit () { this.$emit('input', this.value) }, handleInput (e) { if (e.target.value.length >= this.length) { this.hideKeyboard() } this.handleSubmit() } } } </script> <style scoped lang="less"> .security-code-wrap { display: flex; align-items: center; justify-content: center; } .security-code-container { margin: 0; padding: 0; display: flex; .field-wrap { list-style: none; display: block; height: 40px; width: 40px; line-height: 40px; font-size: 16px; .char-field { font-style: normal; } } } .block-container { justify-content: center; .field-wrap { background-color: #fff; margin: 2px; color: #000; } } .line-container { position: relative; background-color: #fff; &:after { box-sizing: border-box; content: ""; width: 200%; height: 200%; transform: scale(.5); position: absolute; border: 1px solid #d9d9d9; top: 0; left: 0; transform-origin: 0 0; border-radius: 4px; } .field-wrap { flex: 1; position: relative; &:not(:last-child):after { content: ""; width: 1px; height: 50%; position: absolute; right: 0; top: 25%; background-color: #d9d9d9; transform: scaleX(.5); } } } .input-code { position: absolute; left: -9999px; top: -9999px; } </style>
组件使用代码
<security-code v-model="code"></security-code>
结束语
怎么样,484 so easy
一开始的思路也是4个输入框,监听输入完成跳到下一个输入框,这样的做法也能达到目的,不过需要更多的代码去维护这个规则,不够优雅。
目前的做法已经是我能想到最优的解决方案,如果你有更好的实现思路,还望不吝赐教。