Vue3: 产品的花样-反向自动匹配国际区号
简述
正常情况下,我们会像如图所示:
自个选择区号和手机号,然后如果区号和手机号匹配不上就直接表单报错,这是最简单的一种校验方式,但是呢,我们的产品就是比较喜欢折腾前端,啊,说错了。应该说,我们的产品比较亲和用户,站在用户的角度去思考,提高体验感,所以就有了下面这一波设想(我们前端称之为----需求)
先看图:
需求如下:
-
必填
-
输入框提示文案:请输入手机号
-
合法性:手机号格式,根据不同区号,有相应的格式验证
-
交互:
- 获得焦点时,弹出数字键盘,输入内容后,显示一键清空的按钮
- 用户填写后需根据用户填写的手机号,点击“获取验证码”或“登录”,反向匹配国际区号,若当前国际区号匹配则无需变动,若不匹配则提示用户(弹窗如图),用户点击“确定变更”则关闭弹窗且自动变更为匹配的国际区号,若点击“取消”则直接关闭弹窗,不变更国际区号
已有规则可以做反向匹配的:
- 手机号为大陆号码格式(11位),则区号纠正为:+86;
- 香港号码格式(5、7、8、9开头的8位)纠正为:+852;
- 澳门号码格式(6开头的8位),纠正为:+853
-
用户切换登录方式,需自动记忆切换之前的值
实现
第一步:正则表达式
根据产品给出的规则
- 手机号为大陆号码格式(11位),则区号纠正为:+86;
- 香港号码格式(5、7、8、9开头的8位)纠正为:+852;
- 澳门号码格式(6开头的8位),纠正为:+853
可以写出相应的校验表达式:
// 中国大陆手机号码格式(11位),区号纠正为+86
function correctMainlandPhoneNumber(phoneNumber) {
const pattern = /^1\d{10}$/;
if (pattern.test(phoneNumber)) {
return "+86" + phoneNumber;
}
return phoneNumber;
}
// 香港手机号码格式(8位,开头为5、7、8、9),区号纠正为+852
function correctHongKongPhoneNumber(phoneNumber) {
const pattern = /^[5|7|8|9]\d{7}$/;
if (pattern.test(phoneNumber)) {
return "+852" + phoneNumber;
}
return phoneNumber;
}
// 澳门手机号码格式(8位,开头为6),区号纠正为+853
function correctMacauPhoneNumber(phoneNumber) {
const pattern = /^6\d{7}$/;
if (pattern.test(phoneNumber)) {
return "+853" + phoneNumber;
}
return phoneNumber;
}
// 测试示例
const mainlandNumber = "13812345678";
const hongKongNumber = "91234567";
const macauNumber = "61234567";
console.log(correctMainlandPhoneNumber(mainlandNumber)); // Output: +8613812345678
console.log(correctHongKongPhoneNumber(hongKongNumber)); // Output: +85291234567
console.log(correctMacauPhoneNumber(macauNumber)); // Output: +85361234567
也就是:
- +852对应/^([5|7|8|9])\d{7}$/
- +853对应/^[6]\d{7}$/
- +86对应/^1\d{10}$/
但这里要注意一下:我们的产品并没有详细叙说中国大陆的校验规则,查了文档才知道:
中国大陆的手机号码校验规则如下:
- 号码长度为11位数字。
- 第1位为1,表示移动通信。
- 第2位为3、4、5、7、8、9中的一位,表示运营商的归属地区。
运营商归属地区对应如下:
- 3开头:中国电信
- 4开头:中国移动
- 5开头:中国电信
- 7开头:中国移动
- 8开头:中国联通
- 9开头:中国联通
根据以上规则,可以使用以下正则表达式进行中国大陆手机号码的校验:
/^[1][3-9]\d{9}$/
得到了正则表达式,我们就可以进行第二步骤了
第二步:方法封装
template部分:
<template>
<t-dialog
v-model:visible="visible1"
theme="info"
header="提示"
:body="textInfo"
:close-btn="false"
:on-close="closeDialog"
class="login-out-btn"
:confirm-btn="$t('lss.sure_switch')"
:cancel-btn="$t('order.cancel')"
z-index="2501"
@confirm="onClickConfirm"
>
</t-dialog>
</template>
script部分:
// 自动校验手机匹配
const onBlurPhone = (e) => {
console.log(e);
if (!e) return;
const code = checkCodeByPhone(e);
if (code && formData.value.telCode != code) {
// formData.value.telCode = code;
codeV.value = code;
textInfo.value =
proxy.$i18n.locale === 'zh-CN'
? `检测到你输入的手机号对应的国际区号为"+${code}",是否为你自动变更区号`
: `檢測到你輸入的手機號對應的國際區號為"+${code}",是否為你自動變更區號`;
visible1.value = true;
} else {
// MessagePlugin.error('手机号格式错误,请重新输入');
// setTimeout(() => {
// formData.value.telephone = undefined;
// });
}
};
解读:
这段代码是用于自动校验手机匹配的。首先,我定义了一个名为onBlurPhone的函数,该函数接收一个事件参数e。在函数体内部,打印出事件参数e。
接下来,使用checkCodeByPhone函数来检查手机号对应的区号。如果区号存在且与formData对象中的telCode属性不匹配,那么会将区号赋值给codeV,并根据当前语言环境显示一条提示信息,询问用户是否自动变更区号。 随后,将visible1属性设置为true,用于显示某个界面元素。 如图:

如果手机号对应的区号不存在或者与telCode属性匹配,那么代码中暂时没有其他处理逻辑,可以根据实际情况自行添加。
大概的实现步骤就如上面所说的了;对了,选择区号这个组件是自个封装的,有需要代码的可以评论留名哈哈哈!
总结
在实现选择国际区号的弹层交互时,你可以按照以下步骤进行:
- 创建一个按钮或输入框,用于触发选择国际区号弹层的显示;
- 定义一个存储选择的国际区号的变量,以及一个控制弹层显示/隐藏的变量;
- 创建一个方法来控制弹层的显示和隐藏;
- 在弹层中展示国际区号列表,并通过循环渲染进行展示;
- 创建一个方法用于选择国际区号,并在选择完成后更新存储选择的变量的值;
- 根据需求,定制弹层的样式,包括弹出位置、背景色、边框样式等。
我这个小总结提供了一个简单的选择国际区号弹层交互的实现方案,你可以根据实际需求进行定制和扩展。通过封装和优化样式,可以提升用户体验并增加交互的友好性。
扩展--根据ip识别区号
后面产品附加了一个需求: 要根据地区IP自动识别默认手机区号 要通过获取网络IP识别并匹配当前区号,在Vue 3中实现,可以按照以下步骤进行操作:
- 使用
axios
或fetch
等库来获取客户端的公网IP地址。请注意,为了获取客户端的真实IP地址,您需要在前端发送一个请求到一个支持返回真实IP地址的服务器。以下是一个使用axios
获取IP地址的示例代码:
import axios from 'axios';
const getIPAddress = async () => {
try {
const response = await axios.get('https://api.ipify.org?format=json');
return response.data.ip;
} catch (error) {
console.error(error);
return ''; // 处理错误情况
}
};
export default {
data() {
return {
ipAddress: '',
areaCode: ''
};
},
mounted() {
this.getIPAndAreaCode();
},
methods: {
async getIPAndAreaCode() {
const ipAddress = await getIPAddress();
this.ipAddress = ipAddress;
// 根据IP地址发送请求到您的服务器,实现IP地址到区号的映射
// 接下来的步骤将会调用您的服务器API并将匹配到的区号保存在'areaCode'变量中
}
}
};
- 在服务器上设置一个API来处理前端发送的IP地址,并将其与区号进行匹配。您可以使用Node.js、Express或其他后端技术来实现。以下是一个简单的示例:
const express = require('express');
const app = express();
// 根据IP地址匹配区号的路由处理程序
app.get('/api/areaCode/:ip', (req, res) => {
const ip = req.params.ip;
// 这里可以使用IP地址库或其他方法来进行IP地址到区号的映射
// 示例中直接使用一个硬编码的映射
const areaCodeMap = {
'192.168.0.1': 'XXX',
'192.168.0.2': 'YYY',
// 更多IP地址和对应的区号...
};
const areaCode = areaCodeMap[ip] || 'N/A'; // 没有找到匹配的区号时,默认为 'N/A'
res.json({ areaCode });
});
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
- 在Vue组件中调用服务器API来匹配区号:
<template>
<div>
<p>IP Address: {{ ipAddress }}</p>
<p>Area Code: {{ areaCode }}</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
ipAddress: '',
areaCode: ''
};
},
mounted() {
this.getIPAndAreaCode();
},
methods: {
async getIPAndAreaCode() {
try {
const response = await axios.get('http://your-server-ip:3000/api/areaCode/' + this.ipAddress);
this.areaCode = response.data.areaCode;
} catch (error) {
console.error(error);
this.areaCode = 'N/A'; // 处理错误情况
}
}
}
};
</script>
在该代码中,getIPAndAreaCode
方法发送一个GET请求到服务器API来匹配IP地址与区号。请确保将http://your-server-ip
替换为我们实际的服务器IP地址或域名。
转载自:https://juejin.cn/post/7276364913424728121