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

  发布时间:2023-09-19 11:56:17   作者:蜗牛大哥   我要评论
使用uniapp开发打包H5及PC和小程序,H5端实现登录需求一开始是接入阿里云的手机号一键登录服务,但是H5的一键登录功能需要关闭WiFi开启数据才有效,所以换为了四位短信验证码的方式进行登录,此文记录如何实现及期间遇到的问题
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

一、技术栈

uniapp+vue3+javascript

二、实现的效果

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

1、进入页面第一个输入框自动聚焦

2、输入后下一个输入框自动聚焦

3、点击输入区域自动聚焦到无值的第一个输入框(当前一个输入框无值时后一个输入框无法聚焦 )

4、可以复制粘贴填充也可以短信验证码一键登录

5、监听键盘的删除键(Backspace)删除输入的验证码

三、实现逻辑及代码

1、HTML部分:

利用循环渲染4个输入框,第一个输入框可输入最大长度无值时为4(为了复制和验证码填充赋值),有值时最大可输入长度为1。

<template>
    <view class="content">
        <view class="code-area">
            <view class="propmt">已发送4位验证码至 +86 {{ phoneNum }}</view>
            <view class="code-input" @click="handleFocus">
                <input v-for="(item, index) in inputbox" type="number" :key="index" v-model="item.labelValue"
                    class="input-code" :maxlength="index === 0 && isMaxLength ? 4 : 1" @input="onInput($event, index)" />
            </view>
        </view>
    </view>
</template>

2、javascript部分:

1)进入页面第一个输入框自动聚焦:

onMounted(() => {
 ? ?// #ifdef H5
 ? ?// 处理聚焦第一个输入框
 ? ?document.querySelectorAll('.uni-input-input')[0].focus();
 ? ?// #endif
})

2. 输入后下一个输入框自动聚焦,主要是给输入框监听输入事件,判断是否有值,有值就自动聚焦下一个输入框:

// 监听输入输入框 自动聚焦到下一个输入框
const onInput = (e, index) => {
 ? ?// index < 3 ,如果是第4格,不触发光标移动至下一个输入框。
 ? ?if (inputbox[index].labelValue && index < 3) {
 ? ? ? ?nextTick(() => {
 ? ? ? ? ? ?document.querySelectorAll('.uni-input-input')[index + 1].focus()
 ? ? ?  })
 ?  }
}

3)点击输入区域自动聚焦到无值的第一个输入框(当前一个输入框无值时后一个输入框无法聚焦 ),主要是给输入框区域判定一个点击事件,判断当前哪个输入框无值则聚焦:

// 点击输入区域 自动聚焦到空的输入框
const handleFocus = () => {
 ? ?if (focusIndex.value === 4) {
 ? ? ? ?document.querySelectorAll('.uni-input-input')[3].focus();
 ? ? ? ?return;
 ?  }
 ? ?document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
}

4)监听粘贴事件赋值给每个输入框,主要是利用给第一个输入框赋值后,然后给剩下的三个输入框重新赋值(短信验证码填充同理):

// 监听输入区域的粘贴事件
 ? ?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('');
 ? ? ?  }
 ?  })
// 监听第一个输入框的值:为了处理粘贴和短信自动填充时赋值和聚焦
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) => {
 ? ?if (!val) {
 ? ? ? ?// 处理四位输入框为空时再次复制粘贴
 ? ? ? ?isMaxLength.value = true;
 ?  }
?
 ? ?if (val.length === 4) {
 ? ? ? ?// 四位输入框的值已填满 做登录等逻辑操作
 ? ? ? ?console.log('to login')
 ?  }
})

5)监听键盘的删除键(Backspace)删除输入的验证码:

// 监听键盘上的删除按键(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(() => {
document.addEventListener('keydown', handleListenDelete)
})

3、完整javascript代码:

<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) => {
 ? ?if (!val) {
 ? ? ? ?// 处理四位输入框为空时再次复制粘贴
 ? ? ? ?isMaxLength.value = true;
 ?  }
?
 ? ?if (val.length === 4) {
 ? ? ? ?// 四位输入框的值已填满 做登录等逻辑操作
 ? ? ? ?console.log('to login')
 ?  }
})
?
// 点击输入区域 自动聚焦到空的输入框
const handleFocus = () => {
 ? ?if (focusIndex.value === 4) {
 ? ? ? ?document.querySelectorAll('.uni-input-input')[3].focus();
 ? ? ? ?return;
 ?  }
 ? ?document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();
}
?
// 监听输入输入框 自动聚焦到下一个输入框
const onInput = (e, index) => {
 ? ?// index < 3 ,如果是第4格,不触发光标移动至下一个输入框。
 ? ?if (inputbox[index].labelValue && index < 3) {
 ? ? ? ?nextTick(() => {
 ? ? ? ? ? ?document.querySelectorAll('.uni-input-input')[index + 1].focus()
 ? ? ?  })
 ?  }
}
?
?
onBeforeUnmount(() => {
 ? ?document.removeEventListener('keydown', handleListenDelete);
})
?
</script>

四、遇到的问题

1、聚焦实现

由于uniapp使用input是通过封装原生input标签实现的,使用ref获取input dom节点的方式,不能调用focus方法实现聚焦,所以采用原生的获取dom方法实现:

document.querySelectorAll('.uni-input-input')[focusIndex.value].focus();

2、循环渲染input的方法,当某个输入框的值改变其它输入框也跟着改变 原因是我fill()了一个对象,这种方式相当于四个输入框的值都是同一个对象。

let inputbox = reactive(new Array(4).fill({ id: index, labelValue: '' });

3、在做点击输入区域,让焦点自动聚焦到无值的第一个输入框时,发现点击输入框不能实现,点击输入框之间的间隔可以实现。 原因:我给每个输入框设置了diabled属性,让其在上一个输入框有值时才能使用。

:disabled="item.labelValue || (index >= 1 && !inputbox[index - 1].labelValue)"

4、ios的safari浏览器中,验证码填充背景颜色会为黄色: (ps:网上有很多种方法:改变背景色,改变阴影填充等,本人试了都不能实现,下面的方法在iphone14 ios版本为16.1.1中亲测有效)

// 处理去掉safari浏览器填充短信验证码背景色
/deep/ .uni-input-input {
 ? ? ? ? ? ?-webkit-text-fill-color: #262C33;
 ? ? ? ? ? ?transition: background-color 5000s ease-out 0.5s;
 ? ? ?  }

以上就是使用H5实现短信验证码一键登录功能的详细内容,更多关于H5实现短信验证码一键登录的资料请关注程序员之家其它相关文章!

相关文章

  • H5项目怎么打包成APP

    开发uni-app的编辑器HBuilderX可以将H5项目打包成APP,相信很多小伙伴还不知道这个功能,下面将介绍下如何将H5打包成APP,感兴趣的朋友一起看看吧
    2023-04-03
  • 移动端H5实现拍照功能的两种方法

    本文将介绍移动端H5实现拍照功能的两种方法:使用HTML5的input标签和使用第三方插件,帮助读者更好地理解和掌握移动端H5拍照功能的实现,感兴趣的可以了解一下
    2023-03-30
  • 短视频滑动播放在 H5 下的实现方式

    短视频已经无数不在了,但是主体还是使用 app 来承载的,本文讲述 H5 如何实现 app 的视频滑动体验,本文对实现过程中踩到的坑做一个总结,结合示例代码给大家介绍的非常详
    2023-01-05
  • HTML5页面打开微信小程序功能实现

    这篇文章主要介绍了HTML5页面打开微信小程序功能,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-20
  • 如何用H5实现好玩的2048小游戏

    相信大多数读者都玩过一款小游戏 2048,本文主要介绍了如何用H5实现好玩的2048小游戏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
    2022-07-18
  • h5页面背景图很长要有滚动条滑动效果的实现

    这篇文章主要介绍了h5页面背景图很长要有滚动条滑动效果的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-27
  • 详解如何解决H5开发使用wx.hideMenuItems无效果不生效

    这篇文章主要介绍了详解如何解决H5开发使用wx.hideMenuItems无效果不生效,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下
    2021-01-20
  • 关于webview适配H5上传照片或者视频文件的方法

    这篇文章主要介绍了关于webview适配H5上传照片或者视频文件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小
    2020-11-04
  • app内嵌H5 webview 本地缓存问题的解决

    这篇文章主要介绍了app内嵌H5 webview 本地缓存问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一
    2020-10-19
  • h5封装下拉刷新

    这篇文章主要介绍了h5封装下拉刷新,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-25

最新评论

?


http://www.vxiaotou.com