微信小程序 验证码登录 自定义输入框样式

效果

实现

实现思路

将 input 输入框颜色设置透明,定位到自定义输入框的样式上面,点击输入框时聚焦,可以输入内容,再将输入的值分别赋值到已经渲染好的横线上,最后监听 input 的值,实现输入完直接自动登录。

实现代码

父组件 login/index.wxa

<button bindtap="getCode">获取短信验证码</button>

<Code wx:if="{{showCode}}" phoneNumber="{{phone}}" currentTime="{{currentTime}}" clearCode="{{clearCode}}" bindclose="close" bindcodeLogin="codeLogin" bindgetCode="getCode"></Code>
data = {
  showCode: false,
  phone: "",
  currentTime: 0,
  clearCode: false, // 是否清空code输入框
};

// 先登录后选医院 获取短信验证码
getCode() {
  try {
  if($data.currentTime <= 0) {
    var phoneReg = /^1[3456789]\d{9}$/;
    if (!phoneReg.test($data.phone)) {
      wx.showToast({
        title: "请输入正确的手机号",
        icon: "none",
        duration: 2000
      });
      return;
    }
    if (!$data.isConfirm) {
      wx.showToast({
        title: "请勾选用户协议与隐私政策",
        icon: "none",
        duration: 2000
      });
      return;
    }
    // 获取验证码接口
    wx.http.POST({
      url: "/generateCode",
      thirdPartyAPI: true,
      loadTitle: "发送中...",
      isLoad: true,
      needLog: true,
      params: {
        mobile: $data.phone,
        userType: 0,
      },
      success(res) {
        if (res.status == 200) {
          that.setData({currentTime: 60, showCode: true, clearCode: false})
          // 在父组件倒计时,将值 currentTime 传给子组件显示
          let interval = null;
          interval = setInterval(() => {
            $data.currentTime--;
            that.setData({currentTime: $data.currentTime});
            if ($data.currentTime <= 0) {
              clearInterval(interval);
              that.resetCode()
            }
          }, 1000);
        } else {
          wx.showToast({
            title: res.message,
            icon: "none",
            duration: 2000
          });
          that.resetCode()
        }
      },
      fail() {
        that.resetCode()
      }
    });
  } else {
    this.setData({showCode: true})
  }
  } catch (error) {
    wx.http.LOG('发送验证码失败:' + JSON.stringify(error), {}, '', 'error')
  }
}

// 重置获取验证码功能
resetCode() {
  that.setData({
    currentTime: 0
  });
}

codeLogin(e) {
  this.setData({code: e.detail, clearCode: false}) // 这里的 clearCode 要先设置为 false,因为子组件是监听进行操作的,不设置的话值一直为 true,没有变化监听不到
  // 调登录接口
  if() {
    // 登录失败
    // 验证码错误将 clearCode 设置为 true 进行提示和清空输入框
    that.setData({clearCode: true})
  }
}

close(e) {
  this.setData({showCode: false})
}



<config>
{
  "usingComponents": {
    "Code": "./code"
  }
}
</config>

 子组件 login/code.wxa

<template>
  <view class="page">
    <image
      class="codeCloseIcon"
      src="../../../static/img/login/close.svg"
      mode="widthFix"
      bindtap="close"
    ></image>
    <view class="codeCard">
      <view class="weightTitle">输入验证码</view>
      <view>验证码已发送至 {{phoneNumber}}</view>
      <input
        type="number"
        model:value="{{code}}"
        focus="{{focus}}"
        bindtap="onFocus"
        bind:blur="onBlur"
        bind:input="getCodeValue"
        maxlength="6"
        class="input"
      >
      <view class="codeBox">
        <view class="codeBoxItem" wx:for="{{codeBox}}" wx:for-item="item">
          <text class="codeText">{{code[index]}}</text>
          <view class="line" wx:if="{{!code[index] && focus && index == 0}}">|</view>
        </view>
      </view>
      <view class="redText" wx:if="{{clearInput}}">验证码错误,请重新输入</view>
      <view class="codeTextColor" wx:if="{{currentTime > 0}}">{{'重新发送(' + currentTime + 's)'}}</view>
      <view class="codeTextColor" bindtap="getCode" wx:else>{{'重新获取验证码'}}</view>
    </view>
  </view>
</template>
 
<script>
import { Page } from "@wxa/core";
var that, $data;
 
Component({
    properties: {
        phoneNumber: {
            type: String,
            value: ''
        },
        currentTime: {
            type: String,
            value: ''
        },
        clearCode: {
          type: Boolean,
          value: false,
          // 监听
          observer(val) {
            val && this.clear(val)
          }
        }
    },
    data: {
        code: "",
        codeBox: [0, 1, 2, 3, 4, 5], // 用于渲染横线,只需要数组长度
        focus: false, // 输入框焦点
        clearInput: false,
    },
    lifetimes: {
        attached() {
            that = this;
            $data = this.data;
            // 一进入页面自动弹出键盘
            this.onFocus()
        }
    },
    methods: {
        clear(e) {
          this.setData({clearInput: e, code: ""})
        },
        onFocus() {
            this.setData({ focus: true });
        },

        onBlur() {
            this.setData({ focus: false });
        },
        // 获取输入的验证码
        getCodeValue(e) {
            this.setData({clearInput: false})
            let code = e.detail.value;
            if (code && code.length === 6) {
                // 调用父组件的 codeLogin 方法,直接登录
                this.triggerEvent("codeLogin", code)
            }
        },
        close() {
            this.triggerEvent("close")
        },
        getCode() {
          this.triggerEvent("getCode")
        }
    }
})
</script>
 
<config>
{
  "usingComponents": {}
}
</config>
 
<style lang="scss">
.page {
  width: 100%;
  height: 100%;
  color: #333333;
  position: relative;
  background: #ffffff;
  & > .codeCloseIcon {
    position: absolute;
    top: 8%;
    left: 8%;
    width: 60rpx;
  }
  .codeCard {
    position: absolute;
    top: 18%;
    left: 0;
    margin: 0 8%;
    width: 84%;
    display: flex;
    flex-direction: column;
    .weightTitle {
      font-size: 48rpx;
      font-weight: bold;
      margin-bottom: 14rpx;
    }
    .input {
      color: transparent;
      caret-color: transparent;
      // 输入框用这种方式定位,在真机上也不会出现光标
      position: absolute;
      width: 200%;
      height: 100%;
      left: -100%;
      bottom: 20%;
    }
    .codeBox {
      display: flex;
      justify-content: space-between;
      padding-top: 40rpx;
      margin-bottom: 20rpx;
      height: 50rpx;
      .codeBoxItem {
        width: 10%;
        border-bottom: 2rpx solid #979797;
        text-align: center;
        .codeText {
          font-size: 40rpx;
        }
        .line {
          color: #226592;
          font-size: 34rpx;
          animation: cursorImg 1s infinite steps(1, start); // 模拟光标闪动
          @keyframes cursorImg {
            0%,
            100% {
              opacity: 0;
            }
            50% {
              opacity: 1;
            }
          }
        }
      }
    }
    .redText {
      color: #ff0000;
      margin-bottom: 20rpx;
    }
    .codeTextColor {
      color: #979797;
    }
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值