上个月产品提的需求,要求输入邀请码为六位并且每个都是单独的输入框,且每个输入框只能输入一位不可重复。
大概是这样一个的一个样式:
接下来我们来实现:
下面这段是样式
<template>
<div class="ys-verification">
<div class="input-wrapper" v-for="item in amount" :key="item">
<input type="number" oninput="if(value.length>1)value=value.slice(0,1)" @paste="handlePaste" title="code" v-focus="(item - 1) === currentIndex" maxlength="1" @input="handleInput($event,(item-1))" @keyup.delete="onDelete($event,(item-1))" v-model="code[item-1]">
</div>
</div>
</template>
<style lang="less" scoped>
.ys-verification{
width:100%;
display: flex;
justify-content: space-around;
.input-wrapper{
width: 15%;
height: 0;
padding-bottom:20%;
position: relative;
input{
position: absolute;
left: 0;
width: 100%;
height: 100%;
text-align: center;
transition: all 0.3s;
font-size: 7vw;
color: #333333;
background-color: #d7d7d7;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"]{
-moz-appearance: textfield;
}
}
}
</style>
这里是去除掉input属性为number的时候带来的上下箭头:
input[type="number"]{
-moz-appearance: textfield;
}
接下来是JavaScript的逻辑部分:
<script>
export default {
name: 'VerificationCodeInput',
props: {
amount: {
type: Number,
default: 6
}
},
directives: {
focus: {
componentUpdated: function (el, obj) {
obj.value && el.focus()
}
}
},
created () {
this.code = new Array(this.amount).fill('')
},
methods: {
handleInput (e, index) {
this.currentIndex = index
e.target.value = this.validateNumber(e.target.value)
e.target.value !== '' && ++this.currentIndex
if(this.code && this.code.length>=6){
e.srcElement.blur();
}
!this.code.includes('') && this.$emit('onCompleted', this.code.join(''))
},
onDelete (e, index) {
if (e.target.value === '') {
this.currentIndex = index - 1
}
},
validateNumber (val) {
return val.replace(/\D/g, '')
},
handlePaste (e) {
e.preventDefault()
}
},
data () {
return {
code: [],
currentIndex: 0
}
}
}
</script>
整体代码如下
<template>
<div class="ys-verification">
<div class="input-wrapper" v-for="item in amount" :key="item">
<input type="number" oninput="if(value.length>1)value=value.slice(0,1)" @paste="handlePaste" title="code" v-focus="(item - 1) === currentIndex" maxlength="1" @input="handleInput($event,(item-1))" @keyup.delete="onDelete($event,(item-1))" v-model="code[item-1]">
</div>
</div>
</template>
<script>
export default {
name: 'VerificationCodeInput',
props: {
amount: {
type: Number,
default: 6
}
},
directives: {
focus: {
componentUpdated: function (el, obj) {
obj.value && el.focus()
}
}
},
created () {
this.code = new Array(this.amount).fill('')
},
methods: {
handleInput (e, index) {
this.currentIndex = index
e.target.value = this.validateNumber(e.target.value)
e.target.value !== '' && ++this.currentIndex
if(this.code && this.code.length>=6){
e.srcElement.blur();
}
!this.code.includes('') && this.$emit('onCompleted', this.code.join(''))
},
onDelete (e, index) {
if (e.target.value === '') {
this.currentIndex = index - 1
}
},
validateNumber (val) {
return val.replace(/\D/g, '')
},
handlePaste (e) {
e.preventDefault()
}
},
data () {
return {
code: [],
currentIndex: 0
}
}
}
</script>
<style lang="less" scoped>
.ys-verification{
width:100%;
display: flex;
justify-content: space-around;
.input-wrapper{
width: 15%;
height: 0;
padding-bottom:20%;
position: relative;
input{
position: absolute;
left: 0;
width: 100%;
height: 100%;
text-align: center;
transition: all 0.3s;
font-size: 7vw;
color: #333333;
background-color: #d7d7d7;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"]{
-moz-appearance: textfield;
}
}
}
</style>
这样我们就可以封装为组件来适用了