Results,

Effect 1: You can enter verification codes into the input box one by one

Effect two: can paste verification code into the input box

Requirements describe

To achieve the function of modifying the phone number, including the verification of the phone number, input to the verification code.

When you get this function, just think in your mind that you should put 6 input boxes to input the code, and then modify the style of the input box. Just do it.

Draw the UI

So let’s see what the UI diagram looks like

The focused and unfocused styles are shown in the figure above. Since the project is built within the framework of UniApp and uses the input component box that they encapsulate, the style is a little different from that of native input.

In the code

<view class="input-code-view">
    <input :class="['input-text', inputFocusObj['one']?'input-focus':'']"
        type="number"
        maxlength="1"
        v-model="one"
        label-position="left"
        @focus="inputFocusObj['one']=true"
        @blur="inputFocusObj['one']=false">
</view>
Copy the code
.input-code-view {
    opacity: 1;
    border-radius: 32rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    .input-text {
        width: 20rpx;
        height: 96rpx;
        padding: 0 38rpx;
        border-radius: 32rpx;
        background: #f6f6f6;
        border: 2rpx solid #f6f6f6;
        font-size: 32rpx;
        font-family: Alibaba, Alibaba-PuHuiTi;
        font-weight: PuHuiTi;
        color: # 333333;
        line-height: 44rpx;
        text-align: center;
    }
    .input-focus {
        caret-color: #276ef1;
        background: #eff3fe ! important;
        border: 2rpx solid #276ef1 ! important; }}Copy the code

If you look at the uniApp wrapped input, it’s wrapped in several layers

Native input box

It is much easier to modify an already wrapped input box than to modify a native input box. Change the inner style to out of focus, and change the outer style to the border color and cursor color when you focus. So we’re done with the styles, so let’s see what it looks like

You can see that I’ve set the width of the input field to only 10px, which is just about the size of a number. Why is it so small? The main purpose is to make it feel like we are automatically copying the code when we paste it, rather than manually controlling it.

Automatic jump

Who can’t? Listen for the previous input box and focus on the next input box when a number is entered. That’s what I did.

watch: {
    one(val){
        // Get the INPUT box DOM element
        let inputList = document.querySelectorAll('.uni-input-input');
        if(Number(val) > -1) {
            // The second DOM focus
            inputList[1].focus(); }}},Copy the code

Then came the questions…

  1. Because we set the maximum length to 1, typing once is OK; But I couldn’t enter it the second time. Solution: Since the maximum input length is 1, you can’t enter any more, so change it to clean data every time you focus@focus="inputFocusObj['one']=true; one=''"
<view class="input-code-view">
    <input :class="['input-text', inputFocusObj['one']?'input-focus':'']"
        type="number"
        maxlength="1"
        v-model="one"
        label-position="left"
        @focus="inputFocusObj['one']=true; one=''"
        @blur="inputFocusObj['one']=false">
</view>
Copy the code
  1. Problem # 1: If the input field has data, clicking focus will triggerif(Number(val) > -1). Solution: Since an empty string is converted to a Number that is 0, first determine whether it is an empty string
watch: {
    one(val){
        let value = Number(val)
        let inputList = document.querySelectorAll('.uni-input-input');
        if((value || val === '0') && value>-1) {
            inputList[1].focus(); }}},Copy the code

Automatic jump is Ok.

Automatically put in the paste number

This?? Come to think of it, we can only put a copy of the 6-bit verification code in the first input field and then manually assign it to the following input fields.

Because we set the maximum length to 1, this is definitely not replicable. So let’s change the maximum length of the first input field to 6, so you can copy it.

<view class="input-code-view">
    <input :class="['input-text', inputFocusObj['one']?'input-focus':'']"
        type="number"
        maxlength="6"
        v-model="one"
        label-position="left"
        @focus="inputFocusObj['one']=true; one=''"
        @blur="inputFocusObj['one']=false">
</view>
Copy the code

Listen for data one, when the length of the data is greater than 1, we will allocate the extra numbers to the following input box. Why do we use it here

watch: {
    one(val){
        let value = Number(val)
        let inputList = document.querySelectorAll('.uni-input-input');
        if ((value || val === '0') && value>-1) {if (val.length > 1) {
                this.one = val.slice(0.1)
                if (val.length > 1) {
                    this.two = val.slice(1.2)}if (val.length > 2) {
                    this.three = val.slice(2.3)}if (val.length > 3) {
                    this.four = val.slice(3.4)}if (val.length > 4) {
                    this.five = val.slice(4.5)}if (val.length > 5) {
                    this.six = val.slice(5.6)}}else {
                inputList[1].focus(); }}}},Copy the code

Here’s the problem…

  1. When we paste 123456, we find that the second, fourth, and sixth input fields are empty. A closer look at our code shows that when we assigned the first value, we triggered the second focus event, and so on, resulting in the current result. Solution: Define a variable indicating that I am doing a paste action at this time and ask the code not to perform the focus event.

watch: {
    one(val){
        let value = Number(val)
        let inputList = document.querySelectorAll('.uni-input-input');
        if ((value || val === '0') && value>-1) {if (val.length > 1) {
                this.copyFlag = true
                this.one = val.slice(0.1)
                if (val.length > 1) {
                    this.two = val.slice(1.2)}if (val.length > 2) {
                    this.three = val.slice(2.3)}if (val.length > 3) {
                    this.four = val.slice(3.4)}if (val.length > 4) {
                    this.five = val.slice(4.5)}if (val.length > 5) {
                    this.six = val.slice(5.6)}setTimeout(() = > {
                    this.copyFlag = false;
                }, 0);
            } 
            if(!this.copyFlag) {
                inputList[1].focus(); }}},two(val){
        let value = Number(val)
        let inputList = document.querySelectorAll('.uni-input-input');
        if ((value || val === '0') && value>-1&&!this.copyFlag){
            inputList[2].focus(); }},... }Copy the code
  1. Since the first input box can enter 6 characters, when we enter the decimal point, the cursor does not automatically jump, and can keep typing, which must be a problem. Solution: determine whether there is a decimal point, if there is, the data set to 0, and then the cursor jump.
watch: {
    one(val){
        let value = Number(val)
        let inputList = document.querySelectorAll('.uni-input-input');
        if ((value || val === '0') && value>-1) {if (val.length > 1) {
                this.copyFlag = true
                this.one = val.slice(0.1)
                if (val.length > 1) {
                    this.two = val.slice(1.2)}if (val.length > 2) {
                    this.three = val.slice(2.3)}if (val.length > 3) {
                    this.four = val.slice(3.4)}if (val.length > 4) {
                    this.five = val.slice(4.5)}if (val.length > 5) {
                    this.six = val.slice(5.6)}setTimeout(() = > {
                    this.copyFlag = false;
                }, 0);
            } 
            if(!this.copyFlag) {
                inputList[1].focus(); }}else {
            if (val && String(val).indexOf('. ') > -1) {
                this.one = 0;
                inputList[1].focus(); }}}},Copy the code

legacy

  1. When pasting more than 6 digits, the input box value cannot be listened for
  2. Uniapp does not provide listening for keyboard deletion events, so it is not possible to delete data sequently

Do you have any questions to discuss in the comments