项目概述
本项目实现一个注册页面的用户名实时验证功能,使用ajax技术在用户输入时异步检查用户名是否已被占用,提供即时反馈。
技术栈
- 前端:html5, css3, javascript (原生ajax)
- 后端:python flask
- 数据存储:简单文本文件存储已注册用户名
功能需求
- 用户在注册表单输入用户名
- 输入框失去焦点或用户停止输入后自动触发检查
- 实时显示"用户名可用"或"用户名已被占用"提示
- 显示加载状态指示正在检查
项目结构
ajax-form-validation/ ├── static/ │ ├── css/ │ │ └── style.css # 样式文件 │ └── js/ │ └── script.js # ajax逻辑 ├── templates/ │ └── index.html # 注册表单页面 ├── data/ │ └── users.txt # 存储已注册用户名 └── app.py # flask后端
前端设计
html结构
- 注册表单包含用户名、密码等字段
- 用户名输入框添加事件监听
- 提示信息区域用于显示验证结果
css样式
- 输入框状态样式(正常、验证中、有效、无效)
- 提示信息样式(成功、错误、加载中)
- 响应式设计适配不同设备
javascript逻辑
- 使用addeventlistener监听输入事件
- 实现ajax请求函数
- 处理服务器响应并更新ui
- 添加防抖处理避免频繁请求
后端设计
api接口
- get /check-username?username=xxx 检查用户名是否存在
- 返回json格式响应:{ “available”: true/false }
数据处理
- 从users.txt读取已注册用户名
- 检查请求的用户名是否存在
- 返回检查结果
以下是代码:
- index.html
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户注册 - ajax表单验证示例</title>
<link rel="stylesheet" href="../static/css/style.css" rel="external nofollow" />
</head>
<body>
<div class="container">
<h1>用户注册</h1>
<form id="registerform">
<div class="form-group">
<label for="username">用户名:</label>
<div class="input-group">
<input type="text" id="username" name="username" required
minlength="3" maxlength="20" placeholder="请输入用户名">
<div id="usernamefeedback" class="feedback"></div>
</div>
<small>用户名长度为3-20个字符</small>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required
minlength="6" placeholder="请输入密码">
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required placeholder="请输入邮箱">
</div>
<button type="submit" id="submitbtn">注册</button>
</form>
</div>
<script src="../static/js/script.js"></script>
</body>
</html>
- style.css
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'arial', sans-serif;
}
body {
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.container {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 400px;
}
h1 {
text-align: center;
margin-bottom: 25px;
color: #333;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
transition: border-color 0.3s;
}
input:focus {
outline: none;
border-color: #4caf50;
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
}
.input-group {
position: relative;
}
.feedback {
position: absolute;
right: 10px;
top: 50%;
transform: translatey(-50%);
font-size: 14px;
display: none;
}
.feedback.loading {
color: #999;
display: inline;
}
.feedback.available {
color: #4caf50;
display: inline;
}
.feedback.unavailable {
color: #f44336;
display: inline;
}
small {
display: block;
margin-top: 5px;
color: #777;
font-size: 12px;
}
button {
width: 100%;
padding: 12px;
background-color: #4caf50;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
- script.js
document.addeventlistener('domcontentloaded', function() {
const usernameinput = document.getelementbyid('username');
const feedbackelement = document.getelementbyid('usernamefeedback');
const submitbtn = document.getelementbyid('submitbtn');
let isusernameavailable = false;
// 防抖函数
function debounce(func, delay = 500) {
let timeoutid;
return function(...args) {
cleartimeout(timeoutid);
timeoutid = settimeout(() => func.apply(this, args), delay);
};
}
// 检查用户名
function checkusername() {
const username = usernameinput.value.trim();
// 如果用户名为空,不检查
if (!username) {
feedbackelement.style.display = 'none';
isusernameavailable = false;
updatesubmitbutton();
return;
}
// 显示加载状态
feedbackelement.textcontent = '检查中...';
feedbackelement.classname = 'feedback loading';
// 创建ajax请求
const xhr = new xmlhttprequest();
xhr.open('get', `/check-username?username=${encodeuricomponent(username)}`, true);
xhr.onload = function() {
if (xhr.status === 200) {
try {
const response = json.parse(xhr.responsetext);
if (response.available) {
feedbackelement.textcontent = '用户名可用';
feedbackelement.classname = 'feedback available';
isusernameavailable = true;
} else {
feedbackelement.textcontent = '用户名已被占用';
feedbackelement.classname = 'feedback unavailable';
isusernameavailable = false;
}
} catch (e) {
feedbackelement.textcontent = '检查失败,请重试';
feedbackelement.classname = 'feedback unavailable';
isusernameavailable = false;
}
} else {
feedbackelement.textcontent = '服务器错误,请稍后再试';
feedbackelement.classname = 'feedback unavailable';
isusernameavailable = false;
}
updatesubmitbutton();
};
xhr.onerror = function() {
feedbackelement.textcontent = '网络错误,请检查连接';
feedbackelement.classname = 'feedback unavailable';
isusernameavailable = false;
updatesubmitbutton();
};
xhr.send();
}
// 更新提交按钮状态
function updatesubmitbutton() {
submitbtn.disabled = !isusernameavailable || !usernameinput.value.trim();
}
// 监听输入事件,使用防抖
usernameinput.addeventlistener('input', debounce(checkusername));
// 监听失焦事件
usernameinput.addeventlistener('blur', checkusername);
// 表单提交处理
document.getelementbyid('registerform').addeventlistener('submit', function(e) {
e.preventdefault();
if (isusernameavailable) {
// 这里可以添加表单提交逻辑
alert('注册成功!');
}
});
});
运行结果:
data.txt文件中有admin用户名的情况下
用户名存在的情况下,注册不了

用户名不存在的情况下,注册成功

总结
到此这篇关于ajax表单验证项目实战之实时用户名检查功能的文章就介绍到这了,更多相关ajax实时用户名检查内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论