设为首页收藏本站
天天打卡

 找回密码
 立即注册
搜索
查看: 47|回复: 9

使用H5实现短信验证码一键登录功能

[复制链接]

3

主题

61

回帖

189

积分

注册会员

积分
189
发表于 2024-4-20 08:07:31 | 显示全部楼层 |阅读模式
一、技术栈
  1. uniapp+vue3+javascript
复制代码
二、实现的效果

全部代码可见:https://github.com/zzm319/study-summarize.git(分支为code-login)。

1、进入页面第一个输入框自动聚焦
2、输入后下一个输入框自动聚焦
3、点击输入区域自动聚焦到无值的第一个输入框(当前一个输入框无值时后一个输入框无法聚焦 )
4、可以复制粘贴填充也可以短信验证码一键登录
5、监听键盘的删除键(Backspace)删除输入的验证码
三、实现逻辑及代码

1、HTML部分:

利用循环渲染4个输入框,第一个输入框可输入最大长度无值时为4(为了复制和验证码填充赋值),有值时最大可输入长度为1。
  1. <template>
  2.     <view class="content">
  3.         <view class="code-area">
  4.             <view class="propmt">已发送4位验证码至 +86 {{ phoneNum }}</view>
  5.             <view class="code-input" @click="handleFocus">
  6.                 <input v-for="(item, index) in inputbox" type="number" :key="index" v-model="item.labelValue"
  7.                     class="input-code" :maxlength="index === 0 && isMaxLength ? 4 : 1" @input="onInput($event, index)" />
  8.             </view>
  9.         </view>
  10.     </view>
  11. </template>
复制代码
2、javascript部分:

1)进入页面第一个输入框自动聚焦:
  1. onMounted(() => {
  2.    // #ifdef H5
  3.    // 处理聚焦第一个输入框
  4.    document.querySelectorAll('.uni-input-input')[0].focus();
  5.    // #endif
  6. })
复制代码
2. 输入后下一个输入框自动聚焦,主要是给输入框监听输入事件,判断是否有值,有值就自动聚焦下一个输入框:
  1. // 监听输入输入框 自动聚焦到下一个输入框
  2. const onInput = (e, index) => {
  3.    // index < 3 ,如果是第4格,不触发光标移动至下一个输入框。
  4.    if (inputbox[index].labelValue && index < 3) {
  5.        nextTick(() => {
  6.            document.querySelectorAll('.uni-input-input')[index + 1].focus()
  7.        })
  8.    }
  9. }
复制代码
3)点击输入区域自动聚焦到无值的第一个输入框(当前一个输入框无值时后一个输入框无法聚焦 ),主要是给输入框区域判定一个点击事件,判断当前哪个输入框无值则聚焦:
  1. // 点击输入区域 自动聚焦到空的输入框
  2. const handleFocus = () => {
  3.    if (focusIndex.value === 4) {
  4.        document.querySelectorAll('.uni-input-input')[3].focus();
  5.        return;
  6.    }
  7.    document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
  8. }
复制代码
4)监听粘贴事件赋值给每个输入框,主要是利用给第一个输入框赋值后,然后给剩下的三个输入框重新赋值(短信验证码填充同理):
  1. // 监听输入区域的粘贴事件
  2.    document.querySelector('.code-input').addEventListener('paste', (event) => {
  3.        const pasteText = (event.clipboardData || window.clipboardData).getData("text");
  4.        const arr = pasteText.split('').filter(item => /\d/.test(Number(item)));
  5.        const newArr = arr.slice(0, 4).map(item => Number(item));
  6.        if (newArr.length) {
  7.            inputbox[0].labelValue = newArr.join('');
  8.        }
  9.    })
  10. // 监听第一个输入框的值:为了处理粘贴和短信自动填充时赋值和聚焦
  11. watch(() => inputbox[0].labelValue, (val) => {
  12.    if (val) {
  13.        // 处理输入的时候限制输入长度
  14.        isMaxLength.value = false;
  15.    }
  16.    nextTick(() => {
  17.        if (val && val.length >= 2) {
  18.            val.split('').forEach((element, index) => {
  19.                inputbox[index].labelValue = element;
  20.            });
  21.        }

  22.        setTimeout(() => {
  23.            // 加个定时器 避免粘贴两次
  24.            handleFocus();
  25.        })
  26.    })
  27. })
复制代码
注意的是,二次粘贴时需要先重置第一个输入框的最大可输入长度:
  1. watch(() => inputCodeValue.value, async (val) => {
  2.    if (!val) {
  3.        // 处理四位输入框为空时再次复制粘贴
  4.        isMaxLength.value = true;
  5.    }

  6.    if (val.length === 4) {
  7.        // 四位输入框的值已填满 做登录等逻辑操作
  8.        console.log('to login')
  9.    }
  10. })
复制代码
5)监听键盘的删除键(Backspace)删除输入的验证码:
  1. // 监听键盘上的删除按键(Backspace)
  2. const handleListenDelete = (e) => {
  3.    if (e.keyCode === 8 && focusIndex.value > 0) {
  4.        inputbox[focusIndex.value - 1].labelValue = '';
  5.        document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
  6.    }
  7. }

  8. onMounted(() => {
  9. document.addEventListener('keydown', handleListenDelete)
  10. })
复制代码
3、完整javascript代码:
  1. <script setup>import { ref, reactive, watch, onBeforeUnmount, nextTick, onMounted, computed } from 'vue';​let inputbox = reactive(new Array(4).fill().map((item, index) => ({ id: index, labelValue: '' })));let phoneNum = ref('');let isMaxLength = ref(true);​// 四位短信验证码const inputCodeValue = computed(() => inputbox.reduce((pre, item) => pre + item.labelValue, ''))​// 验证码的长度const focusIndex = computed(() => inputCodeValue.value.length)​// 监听键盘上的删除按键(Backspace)const handleListenDelete = (e) => {    if (e.keyCode === 8 && focusIndex.value > 0) {        inputbox[focusIndex.value - 1].labelValue = '';        document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();    }}​​onMounted(() => {    // #ifdef H5    // 处理聚焦第一个输入框    document.querySelectorAll('.uni-input-input')[0].focus()​    document.addEventListener('keydown', handleListenDelete)​    // 监听输入区域的粘贴事件    document.querySelector('.code-input').addEventListener('paste', (event) => {        const pasteText = (event.clipboardData || window.clipboardData).getData("text");        const arr = pasteText.split('').filter(item => /\d/.test(Number(item)));        const newArr = arr.slice(0, 4).map(item => Number(item));        if (newArr.length) {            inputbox[0].labelValue = newArr.join('');        }    })    // #endif})​// 监听第一个输入框的值:为了处理粘贴和短信自动填充时赋值和聚焦watch(() => inputbox[0].labelValue, (val) => {    if (val) {        // 处理输入的时候限制输入长度        isMaxLength.value = false;    }    nextTick(() => {        if (val && val.length >= 2) {            val.split('').forEach((element, index) => {                inputbox[index].labelValue = element;            });        }​        setTimeout(() => {            // 加个定时器 避免粘贴两次            handleFocus();        })    })})​watch(() => inputCodeValue.value, async (val) => {
  2.    if (!val) {
  3.        // 处理四位输入框为空时再次复制粘贴
  4.        isMaxLength.value = true;
  5.    }

  6.    if (val.length === 4) {
  7.        // 四位输入框的值已填满 做登录等逻辑操作
  8.        console.log('to login')
  9.    }
  10. })​// 点击输入区域 自动聚焦到空的输入框
  11. const handleFocus = () => {
  12.    if (focusIndex.value === 4) {
  13.        document.querySelectorAll('.uni-input-input')[3].focus();
  14.        return;
  15.    }
  16.    document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
  17. }​// 监听输入输入框 自动聚焦到下一个输入框
  18. const onInput = (e, index) => {
  19.    // index < 3 ,如果是第4格,不触发光标移动至下一个输入框。
  20.    if (inputbox[index].labelValue && index < 3) {
  21.        nextTick(() => {
  22.            document.querySelectorAll('.uni-input-input')[index + 1].focus()
  23.        })
  24.    }
  25. }​​onBeforeUnmount(() => {    document.removeEventListener('keydown', handleListenDelete);})​</script>
复制代码
四、遇到的问题

1、聚焦实现
由于uniapp使用input是通过封装原生input标签实现的,使用ref获取input dom节点的方式,不能调用focus方法实现聚焦,所以采用原生的获取dom方法实现:
  1. document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
复制代码
2、循环渲染input的方法,当某个输入框的值改变其它输入框也跟着改变 原因是我fill()了一个对象,这种方式相当于四个输入框的值都是同一个对象。
  1. let inputbox = reactive(new Array(4).fill({ id: index, labelValue: '' });
复制代码
3、在做点击输入区域,让焦点自动聚焦到无值的第一个输入框时,发现点击输入框不能实现,点击输入框之间的间隔可以实现。 原因:我给每个输入框设置了diabled属性,让其在上一个输入框有值时才能使用。
  1. :disabled="item.labelValue || (index >= 1 && !inputbox[index - 1].labelValue)"
复制代码
4、ios的safari浏览器中,验证码填充背景颜色会为黄色: (ps:网上有很多种方法:改变背景色,改变阴影填充等,本人试了都不能实现,下面的方法在iphone14 ios版本为16.1.1中亲测有效)
  1. // 处理去掉safari浏览器填充短信验证码背景色
  2. /deep/ .uni-input-input {
  3.            -webkit-text-fill-color: #262C33;
  4.            transition: background-color 5000s ease-out 0.5s;
  5.        }
复制代码
以上就是使用H5实现短信验证码一键登录功能的详细内容,更多关于H5实现短信验证码一键登录的资料请关注脚本之家其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

0

主题

47

回帖

95

积分

注册会员

积分
95
发表于 2024-5-21 11:15:36 | 显示全部楼层
能给个链接吗?我想深入了解一下。

1

主题

52

回帖

123

积分

注册会员

积分
123
发表于 2024-6-3 18:34:12 | 显示全部楼层
我不太确定,可能需要再确认一下。

2

主题

43

回帖

130

积分

注册会员

积分
130
发表于 2024-7-22 03:39:55 | 显示全部楼层
太棒了!感谢分享这个信息!
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 打卡月天数:0
  • 打卡总奖励:93
  • 最近打卡:2024-09-19 09:19:04

0

主题

82

回帖

307

积分

中级会员

积分
307
发表于 2024-8-4 02:34:06 | 显示全部楼层
说得太好了,完全同意!

0

主题

47

回帖

95

积分

注册会员

积分
95
发表于 2024-8-9 16:16:41 | 显示全部楼层
每日一回

1

主题

70

回帖

161

积分

注册会员

积分
161
发表于 2024-9-30 17:39:22 | 显示全部楼层
666666666666666666

0

主题

70

回帖

140

积分

注册会员

积分
140
发表于 2024-10-11 03:25:55 | 显示全部楼层
我不确定这个信息的准确性,请再确认一下

0

主题

44

回帖

87

积分

注册会员

积分
87
发表于 2024-10-12 19:07:32 | 显示全部楼层
友善的讨论氛围是非常重要的。

0

主题

47

回帖

95

积分

注册会员

积分
95
发表于 3 天前 | 显示全部楼层
说得太好了,完全同意!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|爱云论坛 - d.taiji888.cn - 技术学习 免费资源分享 ( 蜀ICP备2022010826号 )|天天打卡

GMT+8, 2024-11-24 10:36 , Processed in 0.100624 second(s), 27 queries .

Powered by i云网络 Licensed

© 2023-2028 正版授权

快速回复 返回顶部 返回列表