注册表单功能案例
效果如下:
一、表单基础结构与元素获取
1. HTML结构设计
注册表单需包含用户输入项(用户名、手机号、验证码等)、验证提示区(错误/正确信息)和操作按钮(获取验证码、提交)
将每个区域的内容都包起来,便于获取元素。
<form class="info">
<!-- 用户名输入 -->
<div class="uname">
<input type="text" name="uname" placeholder="用户名">
<!-- 提示区 -->
<p class="unamep"></p>
</div>
<!-- ... -->
<button>下一步</button>
</form>
2. JS获取DOM元素
//获取表单元素
const info = document.querySelector('.info');
// 获取用户名相关元素
const uname = document.querySelector('.uname input');
const unamep = document.querySelector('.uname p');
// ...
二、表单验证功能实现(以密码为例)
通过正则表达式验证“input中得到输入值校验→提示反馈→返回验证结果”,确保输入符合规则,包括密码长度,重复密码的校验
1. 验证逻辑设计
以密码验证为例,需求:密码需为6-20位字母/[a-zA-Z0-9]{6,20}/。实现步骤:
验证函数
function checkPut(put) {
//定义规则
const law = /[a-zA-Z0-9]{6,20}/;
if (law.test(put.value)) {
putp.innerHTML = '验证正确';
putp.className = 'green';
} else {
putp.innerHTML = '昵称长度为6~20个字符';
putp.className = 'red';
}
// 返回验证结果(true/false),用于后续整体提交校验
return law.test(put.value);
}
- 用正则表达式定义校验规则;
- 通过test方法检测输入值是否符合规则;
- 实时更新提示区内容和样式(gree/red类),给用户直观反馈;
绑定失去焦点事件
当用户输入完成并离开输入框(失去焦点)时触发验证:
uname.addEventListener('blur', checkUname);
2. 其他输入项验证扩展
同理可实现手机号、验证码的验证,仅需调整正则规则和提示信息:
function checkReput() {
//reput符合规则并且上一个密码一致
return (checkPut(reput) && (put.value === reput.value)) ? true : false;
}
reput.addEventListener('blur', function () {
if (checkReput()) {
putp.innerHTML = '验证正确';
//使用className 只添加一个类名
//结构比较简单可以直接使用,避免使用classLIst使用的样式重叠
putp.className = 'green';
} else {
putp.innerHTML = '输入错误或与上次输入的密码不一致';
putp.className = 'red';
}
});
二、倒计时实现
实现“点击获取→按钮禁用→倒计时显示→时间结束恢复可用”。
倒计时核心函数
function startCountdown(duration, onUpdate, onComplete) {
// 总时长
let seconds = duration;
onUpdate(seconds);
// 每秒执行一次
const countdownTimer = setInterval(() => {
seconds--;
onUpdate(seconds); // 传递当前剩余秒数
if (seconds <= 0) {
clearInterval(countdownTimer);
onComplete();
}
}, 1000);
}
绑定“获取验证码”按钮事件
const getcode = document.querySelector('.code span');
getcode.addEventListener('click', () => {
// 1. 禁用按钮,防止重复点击
getcode.disabled = true;
getcode.classList.remove('lightgreen'); // 移除可点击样式
getcode.classList.add('gray'); // 添加禁用样式
getcode.style.cursor = 'not-allowed';
// 2. 开始3秒倒计时
startCountdown(3,
// 每秒更新:显示剩余时间
(seconds) => {
codep.innerHTML = `还有${seconds}秒结束`;
},
// 倒计时结束:恢复按钮状态
() => {
codep.textContent = ''; // 清空提示
getcode.disabled = false;
getcode.classList.remove('gray');
getcode.classList.add('lightgreen');
getcode.style.cursor = 'pointer';
}
);
});
三、表单整体提交控制
阻止默认提交行为
表单默认提交会刷新页面,需先阻止:
const info = document.querySelector('.info');
info.addEventListener('submit', function (e) {
e.preventDefault(); // 阻止默认提交
});
访问验证条件
提交前需检查所有输入项的验证结果(用户名、手机号、验证码、密码、同意条款等):
info.addEventListener('submit', function (e) {
e.preventDefault();
if (!checkCheck() || !checkNumber() || !checkCode() || !checkPut(put) || !checkReput() || !checkCheck()) {
alert('请输入完整');
} else {
if (confirm('将在2秒后跳转')) {
setTimeout(function () {
location.href = 'https://www.baidu.com';
}, 2000)
} else {
console.log('取消跳转');
}
}
});
end完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
padding: 0;
margin: 0;
background-color: rgb(231, 231, 231);
}
.w {
width: 800px;
height: 600px;
margin: 0 auto;
background-color: #fff;
}
h3 {
height: 50px;
font-size: 30px;
}
.contain {
/* display: flex; */
/* display: inline-block; */
width: 300px;
height: 500px;
padding-left: 250px;
/* background-color: pink; */
}
.contain .info div {
display: flex;
position: relative;
}
.contain .info div p {
position: absolute;
text-wrap: nowrap;
top: -10px;
left: 320px;
}
input {
width: 300px;
height: 40px;
border: 1px solid black;
margin-bottom: 20px;
padding-left: 20px;
outline: none;
}
.info .code {
position: relative;
}
.info .code span {
position: absolute;
top: 10px;
right: 5px;
cursor: pointer;
}
.info .agree {
display: flex;
padding: 0 20px 0 20px;
}
.info .agree input {
height: 20px;
}
.info .agree span {
text-wrap: nowrap;
}
.contain .info button {
width: 300px;
height: 40px;
}
.green {
color: green;
}
.red {
color: red;
}
.lightgreen {
color: lightgreen;
}
.gray {
color: gray;
}
</style>
</head>
<body>
<div class="w">
<h3>新用户注册</h3>
<div class="contain">
<form action="" name="info" class="info" autocomplete="on">
<div class="uname">
<input type="text" name="uname" placeholder="用户名">
<p class="unamep"></p>
</div>
<div class="phone">
<input type="text" name="phone" placeholder="手机号码">
<p class="phonep"></p>
</div>
<div class="code">
<input type="text" name="code" placeholder="短信验证码">
<span name="send" class="lightgreen">获得验证码</span>
<p class="codep"></p>
</div>
<div class="put">
<input type="password" name="pwd" id="" placeholder="设置6-20位密码没数字和符号组合" class="put">
<p class="pwdp"></p>
</div>
<div class="reput">
<input type="password" name="pwd" id="" placeholder="确认您的密码" class="reput">
</div>
<div class="agree">
<input type="checkbox" name="" id=""><span><<已同意并阅读用户服务协议>></span>
<p class="agreep"></p>
</div>
<button>下一步</button>
</form>
<div class="tips">
</div>
</div>
</div>
<script>
const info = document.querySelector('.info');
//
const uname = document.querySelector('.uname input');
const unamep = document.querySelector('.uname p');
//
const number = document.querySelector('.phone input');
const numberp = document.querySelector('.phone p');
//
const code = document.querySelector('.info .code input');
const codep = document.querySelector('.info .code p');
const getcode = document.querySelector('.info .code span');
//
const put = document.querySelector('.info .put input');
const putp = document.querySelector('.info .put p');
const reput = document.querySelector('.info .reput input');
//
const agree = document.querySelector('.info .agree input');
const agreep = document.querySelector('.info .agree p');
//
const btn = document.querySelector('.info button');
//
function checkUname() {
const law = /[a-zA-Z]{6,10}/;
if (law.test(uname.value)) {
unamep.innerHTML = '验证正确';
unamep.className = 'green';
} else {
unamep.innerHTML = '昵称长度为6~10个字符';
unamep.className = 'red';
}
return law.test(uname.value);
}
uname.addEventListener('blur', checkUname);
function checkNumber() {
const law = /[1-9][0-9]{4,10}/;
if (law.test(number.value)) {
numberp.innerHTML = '验证正确';
numberp.className = 'green';
} else {
numberp.innerHTML = '请输入正确的手机号';
numberp.className = 'red';
}
return law.test(number.value);
}
number.addEventListener('blur', checkNumber);
function checkCode() {
const law = /[0-9]{6}/;
if (law.test(code.value)) {
codep.innerHTML = '验证正确';
codep.className = 'green';
} else {
codep.innerHTML = '请输入正确的验证码';
codep.className = 'red';
}
return law.test(code.value);
}
code.addEventListener('blur', checkCode);
//
function startCountdown(duration, onUpdate, onComplete) {
let seconds = duration;
onUpdate(seconds);
// 设置每秒更新一次
countdownTimer = setInterval(() => {
seconds--;
onUpdate(seconds);
if (seconds <= 0) {
clearInterval(countdownTimer);
onComplete();
}
}, 1000);
}
getcode.addEventListener('click', () => {
getcode.disabled = true;
getcode.classList.remove('lightgreen');
getcode.classList.add('gray');
codep.innerHTML = ``;
// 开始3秒倒计时
startCountdown(3,
// 更新回调:显示剩余秒数
(seconds) => {
codep.innerHTML = `还有${seconds}秒结束`;
getcode.style.cursor = 'not-allowed';
},
// 完成回调:倒计时结束后执行
() => {
codep.textContent = '';
getcode.disabled = false;
getcode.classList.remove('gray');
getcode.classList.add('lightgreen');
getcode.style.cursor = 'pointer';
}
);
});
//
function checkPut(put) {
const law = /[a-zA-Z0-9]{6,20}/;
if (law.test(put.value)) {
putp.innerHTML = '验证正确';
putp.className = 'green';
} else {
putp.innerHTML = '昵称长度为6~20个字符';
putp.className = 'red';
}
return law.test(put.value);
}
put.addEventListener('blur', function () {
checkPut(put);
});
function checkReput() {
return (checkPut(reput) && (put.value === reput.value)) ? true : false;
}
reput.addEventListener('blur', function () {
if (checkReput()) {
putp.innerHTML = '验证正确';
putp.className = 'green';
} else {
putp.innerHTML = '输入错误或与上次输入的密码不一致';
putp.className = 'red';
}
});
//
function checkCheck() {
if (agree.checked === false) {
agreep.innerHTML = '请先勾选按钮';
agreep.classList.add('red');
} else {
agreep.innerHTML = '';
}
return agree.checked;
}
agree.addEventListener('change', checkCheck);
//
info.addEventListener('submit', function (e) {
// console.log('1');
e.preventDefault();
if (!checkCheck() || !checkNumber() || !checkCode() || !checkPut(put) || !checkReput() || !checkCheck()) {
alert('请输入完整');
} else {
if (confirm('将在2秒后跳转')) {
setTimeout(function () {
location.href = 'https://www.baidu.com';
}, 2000)
} else {
console.log('取消跳转');
}
}
});
</script>
</body>
</html>