首先,我不是原创
原创是https://segmentfault.com/a/1190000023041401
原创是https://segmentfault.com/a/1190000023041401
原创是https://segmentfault.com/a/1190000023041401
重要的原创说三遍
我是在他的基础上,整理出一个vue3可用的简单版本,供大家参考
喏,图都是直接用原创作者的图,因为我不是原创。
MobileCode.vue
:
<template>
<div class="input-box">
<div
class="input-content"
@keydown="keydown"
@keyup="keyup"
@paste="paste"
@mousewheel="mousewheel"
@input="inputEvent"
>
<input
max="9"
min="0"
maxlength="1"
data-index="0"
v-model.trim.number="input[0]"
type="number"
ref="firstinput"
/>
<input
max="9"
min="0"
maxlength="1"
data-index="1"
v-model.trim.number="input[1]"
type="number"
/>
<input
max="9"
min="0"
maxlength="1"
data-index="2"
v-model.trim.number="input[2]"
type="number"
/>
<input
max="9"
min="0"
maxlength="1"
data-index="3"
v-model.trim.number="input[3]"
type="number"
/>
<input
max="9"
min="0"
maxlength="1"
data-index="4"
v-model.trim.number="input[4]"
type="number"
/>
<input
max="9"
min="0"
maxlength="1"
data-index="5"
v-model.trim.number="input[5]"
type="number"
/>
</div>
</div>
</template>
<script>
import { ref } from 'vue'; // vue3需要,vue2不需要可以删掉
export default {
setup() {
// vue3的写法,vue2的话,把这个setup方法删除
// 然后在data()里面定义input就可以
const input = ref(new Array(6).fill(''));
return {
input,
}
},
methods: {
// 解决一个输入框输入多个字符
inputEvent(e) {
var index = e.target.dataset.index * 1
var el = e.target
el.value = el.value
.replace(/Digit|Numpad/i, '')
.replace(/1/g, '')
.slice(0, 1)
this.input[index] = el.value
},
keydown(e) {
var index = e.target.dataset.index * 1
var el = e.target
if (e.key === 'Backspace') {
if (this.input[index] && this.input[index].length > 0) {
this.input[index] = ''
} else {
if (el.previousElementSibling) {
el.previousElementSibling.focus()
this.input[index - 1] = ''
}
}
} else if (e.key === 'Delete') {
if (this.input[index].length > 0) {
this.input[index] = ''
} else {
if (el.nextElementSibling) {
this.input[(index = 1)] = ''
}
}
if (el.nextElementSibling) {
el.nextElementSibling.focus()
}
} else if (e.key === 'Home') {
el.parentElement.children[0] && el.parentElement.children[0].focus()
} else if (e.key === 'End') {
el.parentElement.children[this.input.length - 1] &&
el.parentElement.children[this.input.length - 1].focus()
} else if (e.key === 'ArrowLeft') {
if (el.previousElementSibling) {
el.previousElementSibling.focus()
}
} else if (e.key === 'ArrowRight') {
if (el.nextElementSibling) {
el.nextElementSibling.focus()
}
} else if (e.key === 'ArrowUp') {
if (this.input[index] * 1 < 9) {
this.input[index] = (this.input[index] * 1 + 1).toString()
}
} else if (e.key === 'ArrowDown') {
if (this.input[index] * 1 > 0) {
this.input[index] = (this.input[index] * 1 - 1).toString()
}
}
},
keyup(e) {
var index = e.target.dataset.index * 1
var el = e.target
// 解决输入e的问题
el.value = el.value
.replace(/Digit|Numpad/i, '')
.replace(/1/g, '')
.slice(0, 1)
if (/Digit|Numpad/i.test(e.code)) {
// 必须在这里符直,否则输入框会是空值
this.input[index] = e.code.replace(/Digit|Numpad/i, '')
el.nextElementSibling && el.nextElementSibling.focus()
if (index === 5) {
if (this.input.join('').length === 6) {
document.activeElement.blur()
}
}
} else {
if (this.input[index] === '') {
this.input[index] = ''
}
}
this.$emit( 'complete', this.input.slice());
},
mousewheel(e) {
var index = e.target.dataset.index
if (e.wheelDelta > 0) {
if (this.input[index] * 1 < 9) {
this.input[index] = (this.input[index] * 1 + 1).toString()
}
} else if (e.wheelDelta < 0) {
if (this.input[index] * 1 > 0) {
this.input[index] = (this.input[index] * 1 - 1).toString()
}
} else if (e.key === 'Enter') {
if (this.input.join('').length === 6) {
document.activeElement.blur()
this.$emit('complete', this.input.slice())
}
}
},
paste(e) {
// 当进行粘贴时
e.clipboardData.items[0].getAsString((str) => {
if (str.toString().length === 6) {
document.activeElement.blur();
this.input = str.split('');
this.$emit( 'complete', this.input.slice())
} else {
// 如果粘贴内容不合规,清除所有内容
this.input[0] = new Array(6)
}
})
},
},
mounted() {
// 等待dom渲染完成,在执行focus,否则无法获取到焦点
this.$nextTick(() => {
this.$refs.firstinput.focus()
})
},
emits: ['complete'],
}
</script>
<style lang="scss" scoped>
.input-box {
.input-content {
width: 512px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
input {
color: inherit;
font-family: inherit;
border: 0;
outline: 0;
border-bottom: 1px solid #919191;
height: 60px;
width: 60px;
font-size: 44px;
text-align: center;
}
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
appearance: none;
margin: 0;
}
}
</style>
父组件调用:
<MobileCode @complete="onComplete" />
<script setup>
// vue3写法,vue2在methods里定义
const onComplete = (val) => {
console.log('complete', val);
}
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。