目录
原生JS实现注册表单,滑块验证,短信验证码等。
一、编辑表单询盘结构
1、确定注册接口所需参数
本文中案例注册接口所需参数有:
| 参数 | key |
| 电话(companyTelephone) | companyTelephone |
| 短信(smsCode) | smsCode |
| 密码(pwd) | pwd |
| 姓名(contactPerson) | contactPerson |
| 公司名称(companyName) | companyName |
| 邮箱(companyEmail) | companyEmail |
| _appId(_appId) | _appId |
2、编写表单HTML结构
需要注意的是,如果在wordpress中使用这种自定义组件的询盘表单,使用css样式表的 方法添加样式可能会出现优先级不够从而导致与默认表单样式冲突的问题,在页面中部分样式会显示不全出现乱版,所以我此处将部分样式编写到了标签内用以提升样式优先级,避免被默认表单样式冲突掉。
在对应的元素上添加了对应的id、name、class属性,以方便后面获取表单数据。
<!-- 表单 -->
<form id="rForm" style="width:500px;box-shadow: 0 10px 20px 10px #d8d7d7; padding: 25px 0;margin: 50px auto;border-radius: 20px;">
<div class="row" style="text-align: center;margin-bottom: 10px;display: flex;align-items: center;justify-content: center;">
<div class="phone-header" style="width: 10%;height: 45px;background-color: #f9f9f9;border-top-left-radius: 20px;border-bottom-left-radius: 20px;line-height: 45px;border-right: 2px solid #ffffff;color: #858A96;font-size: 16px">+86</div>
<input type="text" id="phone" name="companyTelephone" required class="customizeInquiry" placeholder="请输入您的手机号码(必填)" style="width: 50%;height: 45px;border-radius: 20px;border-top-left-radius: 0px;border-bottom-left-radius: 0px;background-color: #f9f9f9;text-indent: 2em;border: none;">
</div>
<!-- 验证码滑块 -->
<div id="nc" style="position: relative;width: 60%;margin: 20px auto;"></div>
<div class="row" style="text-align: center;margin-bottom: 10px;display: flex;align-items: center;justify-content: center;">
<input type="text" id="yzm" name="smsCode" required class="customizeInquiry" placeholder="短信验证码" style="width: 40%;height: 45px;border-radius: 20px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;background-color: #f9f9f9;text-indent: 2em;border: none;">
<div class="getyzm" style="width: 20%;height: 45px;background-color: #f9f9f9;border-top-right-radius: 20px;border-bottom-right-radius: 20px;line-height: 45px;border-left: 2px solid #ffffff;transition: all 0.3s;cursor: pointer;margin-left: 1px;font-size: 16px;color:#858A96">获取验证码</div>
</div>
<div class="row" style="text-align: center;margin-bottom: 10px;">
<input type="text" id="password" name="pwd" required class="customizeInquiry" placeholder="设置登录密码" style="width: 60%;height: 45px;background-color: #f9f9f9;text-indent: 2em;border-radius: 20px;border: none;">
</div>
<div class="row" style="text-align: center;margin-bottom: 10px;">
<input type="text" id="repassword" name="repassword" required placeholder="请再次输入登录密码" style="width: 60%;height: 45px;background-color: #f9f9f9;text-indent: 2em;border-radius: 20px;border: none;">
</div>
<div class="row" style="text-align: center;margin-bottom: 10px;">
<input type="text" id="name" name="contactPerson" required class="customizeInquiry" placeholder="请输入您的姓名" style="width: 60%;height: 45px;background-color: #f9f9f9;text-indent: 2em;border-radius: 20px;border: none;">
</div>
<div class="row" style="text-align: center;margin-bottom: 10px;">
<input type="text" id="company" name="companyName" required class="customizeInquiry" placeholder="请输入您的公司名称(必填)" style="width: 60%;height: 45px;background-color: #f9f9f9;text-indent: 2em;border-radius: 20px;border: none;">
</div>
<div class="row" style="text-align: center;margin-bottom: 10px;">
<input type="text" id="email" name="companyEmail" required class="customizeInquiry" placeholder="请输入您的邮箱(必填)" style="width: 60%;height: 45px;background-color: #f9f9f9;text-indent: 2em;border-radius: 20px;border: none;">
</div>
<div class="tijiao" style="text-align: center;padding-top: 10px;">
<input value="立即注册" id="customizeInquiryBtn" style="width: 60%;height: 45px;background-color: #ff7602;text-indent: 0;border-radius: 20px;border: none;color: #ffffff;cursor: pointer;transition: all 0.5s;text-align: center;">
</div>
<div class="login" style="text-align: center;padding-top: 10px;font-size: 16px;">
已有账号?<a href="/login" style="text-decoration: none;color:#ff7602;">立即登录</a>
</div>
<div class="back" style="text-align: center;font-size: 16px;">
了解服务详情?<a href="/index" style="text-decoration: none;color:#4095e5;">返回官网</a>
</div>
</form>
二、编写style样式
1、非表单元素样式
这里写的是表单中非input等元素的自定义块样式,例如短信验证码获取按钮,激活后样式,电话头部等样式。
/* 询盘 */
#rform{
padding: 25px 0;
margin: 0;
}
#rform .row {
text-align: center;
margin-bottom: 10px;
}
.phone-header{
width: 10%;
height: 45px;
background-color: #f9f9f9;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
line-height: 45px;
border-right: 2px solid #ffffff;
}
.getyzm{
width: 20%;
height: 45px;
background-color: #f9f9f9;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
line-height: 45px;
border-left: 2px solid #ffffff;
transition: all 0.3s;
cursor: pointer;
margin-left: 1px;
pointer-events: none;
cursor: default;
}
.getyzmok{
color: #000000 !important;
pointer-events: visible;
}
.getyzm:hover{
background-color: #ff7602 !important;
color: #ffffff !important;
font-size: 16px;
}
#rform input {
width: 60%;
height: 45px;
border-radius: 20px;
border: none;
background-color: #f9f9f9;
text-indent: 2em;
}
#rform input:focus{
outline: 1px solid #ff7602;
}
#rform .tijiao{
text-align: center;
padding-top: 10px;
}
#rform .tijiao input{
text-indent: 0;
background-color: #ff7602;
cursor: pointer;
color: #ffffff;
transition: all 0.5s;
}
#rform .tijiao input:hover{
background-color: #ff7602c4;
}
@media screen and (max-width:768px) {
.getyzm{
font-size: 12px !important;
}
}
完成HTML和CSS后的页面样式预览:

三、引入阿里云滑块验证
参考文档:如何集成滑动验证的前端页面代码_验证码(Captcha)-阿里云帮助中心
1、引入阿里短信接口CDN
<script src="https://g.alicdn.com/AWSC/AWSC/awsc.js"></script>
2、实例化nc对象
在实例化nc之前先声明几个后面调用短信验证码接口时会用到的变量,参数在滑块验证成功后会返回,并将返回的参数放到对应的声明变量中,同时给获取验证码按钮添加激活类,回复按钮可点击状态,本例中短信接口所需参数为:
| 参数 | key |
| 手机号 | phoneNumber |
| 会话ID | sessionId |
| 类型 | type |
| 签名串 | sig |
| 请求唯一标识 | token |
实例化中nc的对应appkey需要在阿里云后台控制台获取,请输入对应的参数,否则会验证失败。
let phoneNumberV = '';
let sessionIdV = '';
let sigV = '';
let tokenV = '';
let ncInstance;
// 实例化nc
AWSC.use("nc", function (state, module) {
// 初始化
ncInstance = module.init({
// 应用类型标识。它和使用场景标识(scene字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在阿里云验证码控制台的配置管理页签找到对应的appkey字段值,请务必正确填写。
appkey: "XXXXXXXXXXXXXXXXXXXX",
//使用场景标识。它和应用类型标识(appkey字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在阿里云验证码控制台的配置管理页签找到对应的scene值,请务必正确填写。
scene: "nc_register",
// 声明滑动验证需要渲染的目标ID。
renderTo: "nc",
//前端滑动验证通过时会触发该回调参数。您可以在该回调参数中将会话ID(sessionId)、签名串(sig)、请求唯一标识(token)字段记录下来,随业务请求一同发送至您的服务端调用验签。
success: function (data) {
phoneNumberV = document.getElementById('phone').value; // 获取手机号
sessionIdV = data.sessionId;
tokenV = data.token;
sigV = data.sig;
const getyzmbtn = document.querySelector('.getyzm');
getyzmbtn.classList.add('getyzmok');
},
// 滑动验证失败时触发该回调参数。
fail: function (failCode) {
window.console && console.log(failCode)
},
// 验证码加载出现异常时触发该回调参数。
error: function (errorCode) {
window.console && console.log(errorCode)
}
});
});
滑块验证成功反馈:

四、调用短信验证码接口
短信验证码流程图(图源阿里云),不过我们这里最后拿到验证码后调用的是注册接口,原理相通。

1、给获取按钮绑定点击事件
给获取验证码按钮绑定点击事件,点击后移除按钮的激活类,恢复到不可点击状态,判断滑块验证是否成功,如果是已经成功的重置滑块状态。创建FormData对象,将上面滑块验证成功后回调给的对应参数添加到对象中用以调用短信接口。
document.addEventListener('DOMContentLoaded', function() {
// 点击获取验证码按钮
document.querySelector('.getyzm').addEventListener('click', function() {
const getyzmbtn = document.querySelector('.getyzm');
getyzmbtn.classList.remove('getyzmok');
if (ncInstance) {
ncInstance.reset(); // 触发滑块验证
}
// 创建 FormData 对象
const formData = new FormData();
formData.append('mobile', phoneNumberV);
formData.append('type', 1);
formData.append('sessionId', sessionIdV);
formData.append('sig', sigV);
formData.append('token', tokenV);
// 发送 POST 请求到指定接口
fetch('https://example.net/send', {
method: 'POST',
body:formData
})
.then(response => response.json())
.then(data => {
console.log('Response:', data);
alert(data.message)
})
.catch(error => {
console.error('Error:', error);
alert(error.message)
});
});
})
2、测试短信验证码获取
因为这里我的手机号已经注册过了,所以接口返回已被注册,同时也说明接口获取的滑块回调参数是正确的,接口正常调用了。如果是未注册的手机号,这里应该会弹出success发送成功,同时手机上收到短信验证码smsCode。

五、调用注册接口
1、引入jQuery
引入jQuery,方便获取表单中的各项数据和发起请求。
<script src="https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js"></script>
2、设置防抖节流
设置变量isSubmitting 判断是否提交,如果为true则是已经提交,提示请勿重复提交,如果为false可以继续执行。
$(document).ready(function() {
let isSubmitting = false; // Track submission state
$('#customizeInquiryBtn').on('click', function(event) {
event.preventDefault(); // 防止表单的默认提交行为
// Check if already submitting
if (isSubmitting) {
alert('请勿重复提交');
return;
}
isSubmitting = true;
)}
)}

3、表单数据获取
定义变量isValid判断是否符合提交规则,使用jQuery根据class获取表单中各项数据放入inputs,定义变量enquiryContent存放表单数据,定义agreementCheckbox判断是否勾选复选框(如果有的话,本例中没有该选项,但不影响),对inputs进行遍历查看是否为空,对于非空的数据存储在enquiryContent中,当有空的选项时进行提示,当遍历完成后切都不为空时拿到所有选项数据并存储在enquiryContent中,此时isValid为true,否则isValid为false。
$(document).ready(function() {
let isSubmitting = false; // Track submission state
$('#customizeInquiryBtn').on('click', function(event) {
event.preventDefault(); // 防止表单的默认提交行为
// Check if already submitting
if (isSubmitting) {
alert('请勿重复提交');
return;
}
isSubmitting = true; // Set to true to prevent further submissions
// 获取非hidden的输入框的数据
let isValid = true;
const inputs = $('.customizeInquiry');
const enquiryContent = {};
// 通过ID获取checkbox元素
var agreementCheckbox = document.getElementById('agreement');
// 循环查看是否表单为空
inputs.each(function() {
const value = $(this).val();
const name = $(this).attr('name');
// console.log($(this).context.id);
if ($(this).attr('type') === 'checkbox') {
// 处理checkbox
if ($(this).is(':checked')) {
if (!enquiryContent[name]) {
enquiryContent[name] = [];
}
enquiryContent[name].push($(this).attr('id'));
}
} else {
if (!value) {
$(this).siblings('.empty-tip').show();
isValid = false;
} else {
$(this).siblings('.empty-tip').hide();
enquiryContent[name] = value;
}
}
});
});
});
4、验证密码是否相同
使用jQuery根据id拿到输入框中的密码和重复密码的value值,进行判断是否相同,不同则isValid返回false,并进行提示。
$(document).ready(function() {
let isSubmitting = false; // Track submission state
$('#customizeInquiryBtn').on('click', function(event) {
event.preventDefault(); // 防止表单的默认提交行为
// Check if already submitting
if (isSubmitting) {
alert('请勿重复提交');
return;
}
isSubmitting = true; // Set to true to prevent further submissions
// 获取非hidden的输入框的数据
let isValid = true;
const inputs = $('.customizeInquiry');
const enquiryContent = {};
// 通过ID获取checkbox元素
var agreementCheckbox = document.getElementById('agreement');
// 循环查看是否表单为空
inputs.each(function() {
const value = $(this).val();
const name = $(this).attr('name');
// console.log($(this).context.id);
if ($(this).attr('type') === 'checkbox') {
// 处理checkbox
if ($(this).is(':checked')) {
if (!enquiryContent[name]) {
enquiryContent[name] = [];
}
enquiryContent[name].push($(this).attr('id'));
}
} else {
if (!value) {
$(this).siblings('.empty-tip').show();
isValid = false;
} else {
$(this).siblings('.empty-tip').hide();
enquiryContent[name] = value;
}
}
});
// 检查密码和确认密码是否匹配
const password = $('#password').val();
const repassword = $('#repassword').val();
if (password !== repassword) {
alert('密码和确认密码不相同,请确认密码一致!');
isValid = false;
}
});
});

5、验证是否通过
验证isValid的值,为true则进行表单数据处理,否则提示错误。
$(document).ready(function() {
let isSubmitting = false; // Track submission state
$('#customizeInquiryBtn').on('click', function(event) {
event.preventDefault(); // 防止表单的默认提交行为
// Check if already submitting
if (isSubmitting) {
alert('请勿重复提交');
return;
}
isSubmitting = true; // Set to true to prevent further submissions
// 获取非hidden的输入框的数据
let isValid = true;
const inputs = $('.customizeInquiry');
const enquiryContent = {};
// 通过ID获取checkbox元素
var agreementCheckbox = document.getElementById('agreement');
// 循环查看是否表单为空
inputs.each(function() {
const value = $(this).val();
const name = $(this).attr('name');
// console.log($(this).context.id);
if ($(this).attr('type') === 'checkbox') {
// 处理checkbox
if ($(this).is(':checked')) {
if (!enquiryContent[name]) {
enquiryContent[name] = [];
}
enquiryContent[name].push($(this).attr('id'));
}
} else {
if (!value) {
$(this).siblings('.empty-tip').show();
isValid = false;
} else {
$(this).siblings('.empty-tip').hide();
enquiryContent[name] = value;
}
}
});
// 检查密码和确认密码是否匹配
const password = $('#password').val();
const repassword = $('#repassword').val();
if (password !== repassword) {
alert('密码和确认密码不相同,请确认密码一致!');
isValid = false;
}
// 验证是否通过
if (isValid) {
// console.log(enquiryContent)
// 对表单结果进行处理
// console.log(JSON.stringify(enquiryContent));
} else {
alert("请完善表单!")
}
});
});

6、调用注册接口
当isValid为true时,对表单数据进行处理,创建DormData对象,将表单中的值赋值给对应参数,最终拿到formData2,调用注册接口携带formData2参数发起POST请求,请求成功后设置定时器0.1秒后跳转登录地址,并设置定时器在3秒后重置isSubmitting参数为false,控制在发起请求3秒内不能再次提交请求。
$(document).ready(function() {
let isSubmitting = false; // Track submission state
$('#customizeInquiryBtn').on('click', function(event) {
event.preventDefault(); // 防止表单的默认提交行为
// Check if already submitting
if (isSubmitting) {
alert('请勿重复提交');
return;
}
isSubmitting = true; // Set to true to prevent further submissions
// 获取非hidden的输入框的数据
let isValid = true;
const inputs = $('.customizeInquiry');
const enquiryContent = {};
// 通过ID获取checkbox元素
var agreementCheckbox = document.getElementById('agreement');
// 循环查看是否表单为空
inputs.each(function() {
const value = $(this).val();
const name = $(this).attr('name');
// console.log($(this).context.id);
if ($(this).attr('type') === 'checkbox') {
// 处理checkbox
if ($(this).is(':checked')) {
if (!enquiryContent[name]) {
enquiryContent[name] = [];
}
enquiryContent[name].push($(this).attr('id'));
}
} else {
if (!value) {
$(this).siblings('.empty-tip').show();
isValid = false;
} else {
$(this).siblings('.empty-tip').hide();
enquiryContent[name] = value;
}
}
});
// 检查密码和确认密码是否匹配
const password = $('#password').val();
const repassword = $('#repassword').val();
if (password !== repassword) {
alert('密码和确认密码不相同,请确认密码一致!');
isValid = false;
}
// 验证是否通过
if (isValid) {
// console.log(enquiryContent.companyTelephone)
// 对表单结果进行处理
// console.log(JSON.stringify(enquiryContent));
// 创建 FormData 对象
const formData2 = new FormData();
formData2.append('companyTelephone', enquiryContent.companyTelephone);
formData2.append('smsCode', enquiryContent.smsCode);
formData2.append('pwd', enquiryContent.pwd);
formData2.append('contactPerson', enquiryContent.contactPerson);
formData2.append('companyName', enquiryContent.companyName);
formData2.append('companyEmail', enquiryContent.companyEmail);
formData2.append('_appId', 8);
// 发送 POST 请求到指定接口
fetch('https://example.net/register', {
method: 'POST',
body:formData2
})
.then(response => response.json())
.then(data => {
console.log('Response:', data);
alert(data.message);
if(data.message == 'success'){
// alert('注册成功!');
window._agl && window._agl.push(['track', ['success', {t: 3}]])
setTimeout(function(){
window.location.href = '/login';
},100)
}
})
.catch(error => {
console.error('Error:', error);
alert(error.message)
})
.finally(() => {
// Reset isSubmitting after 3 seconds
setTimeout(() => {
isSubmitting = false;
}, 3000);
});
} else {
alert("请完善表单!")
}
});
});
六、小结
注意替换接口地址为真实接口地址。
在一些时候可能会用到注册渠道追踪,可以在isValid验证通过后添加参数source(根据后端接口情况,此处默认source)提交给接口。先获取当前页面地址参数queryParamsValue,再通过get方法获取参数数据(可以是多个,一起拼接为一个参数就行,此处举例使用了两个参数,source和keyword),并将参数source添加入formData2一并发送给注册接口,从而在后端接收注册渠道信息。
// 获取页面来源
const queryParamsValue = new URLSearchParams(window.location.search);
const sourceValue= queryParamsValue.get('source');
const keywordValue = queryParamsValue.get('keyword');
const source = ('注册来源是:' + sourceValue + ',关键词是:' + keywordValue)
示例:
当前注册页面地址:https://example.net/register?source=baidu&keyword=凉风听雪
获取注册渠道来源source:


2万+

被折叠的 条评论
为什么被折叠?



