AJAX表單驗(yàn)證項(xiàng)目實(shí)戰(zhàn)之實(shí)時(shí)用戶(hù)名檢查功能
項(xiàng)目概述
本項(xiàng)目實(shí)現(xiàn)一個(gè)注冊(cè)頁(yè)面的用戶(hù)名實(shí)時(shí)驗(yàn)證功能,使用AJAX技術(shù)在用戶(hù)輸入時(shí)異步檢查用戶(hù)名是否已被占用,提供即時(shí)反饋。
技術(shù)棧
- 前端:HTML5, CSS3, JavaScript (原生AJAX)
- 后端:Python Flask
- 數(shù)據(jù)存儲(chǔ):簡(jiǎn)單文本文件存儲(chǔ)已注冊(cè)用戶(hù)名
功能需求
- 用戶(hù)在注冊(cè)表單輸入用戶(hù)名
- 輸入框失去焦點(diǎn)或用戶(hù)停止輸入后自動(dòng)觸發(fā)檢查
- 實(shí)時(shí)顯示"用戶(hù)名可用"或"用戶(hù)名已被占用"提示
- 顯示加載狀態(tài)指示正在檢查
項(xiàng)目結(jié)構(gòu)
ajax-form-validation/ ├── static/ │ ├── css/ │ │ └── style.css # 樣式文件 │ └── js/ │ └── script.js # AJAX邏輯 ├── templates/ │ └── index.html # 注冊(cè)表單頁(yè)面 ├── data/ │ └── users.txt # 存儲(chǔ)已注冊(cè)用戶(hù)名 └── app.py # Flask后端
前端設(shè)計(jì)
HTML結(jié)構(gòu)
- 注冊(cè)表單包含用戶(hù)名、密碼等字段
- 用戶(hù)名輸入框添加事件監(jiān)聽(tīng)
- 提示信息區(qū)域用于顯示驗(yàn)證結(jié)果
CSS樣式
- 輸入框狀態(tài)樣式(正常、驗(yàn)證中、有效、無(wú)效)
- 提示信息樣式(成功、錯(cuò)誤、加載中)
- 響應(yīng)式設(shè)計(jì)適配不同設(shè)備
JavaScript邏輯
- 使用addEventListener監(jiān)聽(tīng)輸入事件
- 實(shí)現(xiàn)AJAX請(qǐng)求函數(shù)
- 處理服務(wù)器響應(yīng)并更新UI
- 添加防抖處理避免頻繁請(qǐng)求
后端設(shè)計(jì)
API接口
- GET /check-username?username=xxx 檢查用戶(hù)名是否存在
- 返回JSON格式響應(yīng):{ “available”: true/false }
數(shù)據(jù)處理
- 從users.txt讀取已注冊(cè)用戶(hù)名
- 檢查請(qǐng)求的用戶(hù)名是否存在
- 返回檢查結(jié)果
以下是代碼:
- 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>用戶(hù)注冊(cè) - AJAX表單驗(yàn)證示例</title>
<link rel="stylesheet" href="../static/css/style.css" rel="external nofollow" />
</head>
<body>
<div class="container">
<h1>用戶(hù)注冊(cè)</h1>
<form id="registerForm">
<div class="form-group">
<label for="username">用戶(hù)名:</label>
<div class="input-group">
<input type="text" id="username" name="username" required
minlength="3" maxlength="20" placeholder="請(qǐng)輸入用戶(hù)名">
<div id="usernameFeedback" class="feedback"></div>
</div>
<small>用戶(hù)名長(zhǎng)度為3-20個(gè)字符</small>
</div>
<div class="form-group">
<label for="password">密碼:</label>
<input type="password" id="password" name="password" required
minlength="6" placeholder="請(qǐng)輸入密碼">
</div>
<div class="form-group">
<label for="email">郵箱:</label>
<input type="email" id="email" name="email" required placeholder="請(qǐng)輸入郵箱">
</div>
<button type="submit" id="submitBtn">注冊(cè)</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;
// 防抖函數(shù)
function debounce(func, delay = 500) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
// 檢查用戶(hù)名
function checkUsername() {
const username = usernameInput.value.trim();
// 如果用戶(hù)名為空,不檢查
if (!username) {
feedbackElement.style.display = 'none';
isUsernameAvailable = false;
updateSubmitButton();
return;
}
// 顯示加載狀態(tài)
feedbackElement.textContent = '檢查中...';
feedbackElement.className = 'feedback loading';
// 創(chuàng)建AJAX請(qǐng)求
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 = '用戶(hù)名可用';
feedbackElement.className = 'feedback available';
isUsernameAvailable = true;
} else {
feedbackElement.textContent = '用戶(hù)名已被占用';
feedbackElement.className = 'feedback unavailable';
isUsernameAvailable = false;
}
} catch (e) {
feedbackElement.textContent = '檢查失敗,請(qǐng)重試';
feedbackElement.className = 'feedback unavailable';
isUsernameAvailable = false;
}
} else {
feedbackElement.textContent = '服務(wù)器錯(cuò)誤,請(qǐng)稍后再試';
feedbackElement.className = 'feedback unavailable';
isUsernameAvailable = false;
}
updateSubmitButton();
};
xhr.onerror = function() {
feedbackElement.textContent = '網(wǎng)絡(luò)錯(cuò)誤,請(qǐng)檢查連接';
feedbackElement.className = 'feedback unavailable';
isUsernameAvailable = false;
updateSubmitButton();
};
xhr.send();
}
// 更新提交按鈕狀態(tài)
function updateSubmitButton() {
submitBtn.disabled = !isUsernameAvailable || !usernameInput.value.trim();
}
// 監(jiān)聽(tīng)輸入事件,使用防抖
usernameInput.addEventListener('input', debounce(checkUsername));
// 監(jiān)聽(tīng)失焦事件
usernameInput.addEventListener('blur', checkUsername);
// 表單提交處理
document.getElementById('registerForm').addEventListener('submit', function(e) {
e.preventDefault();
if (isUsernameAvailable) {
// 這里可以添加表單提交邏輯
alert('注冊(cè)成功!');
}
});
});
運(yùn)行結(jié)果:
data.txt文件中有admin用戶(hù)名的情況下
用戶(hù)名存在的情況下,注冊(cè)不了

用戶(hù)名不存在的情況下,注冊(cè)成功

總結(jié)
到此這篇關(guān)于AJAX表單驗(yàn)證項(xiàng)目實(shí)戰(zhàn)之實(shí)時(shí)用戶(hù)名檢查功能的文章就介紹到這了,更多相關(guān)AJAX實(shí)時(shí)用戶(hù)名檢查內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Ajax進(jìn)行文件與其他參數(shù)的上傳功能(java開(kāi)發(fā))
這篇文章主要介紹了使用Ajax進(jìn)行文件與其他參數(shù)的上傳功能(java開(kāi)發(fā)),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01
解決ajax傳過(guò)來(lái)的值后臺(tái)接收不到的問(wèn)題
今天小編就為大家分享一篇解決ajax傳過(guò)來(lái)的值后臺(tái)接收不到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
JQuery+ajax實(shí)現(xiàn)批量上傳圖片(自寫(xiě))
jquery+ajax方式實(shí)現(xiàn)單張圖片上傳的代碼是可以搜的到,實(shí)現(xiàn)批量上傳圖片的程序卻沒(méi)搜索到于是自己寫(xiě)了個(gè),感興趣的朋友可以參考下2013-04-04
淺談Ajax相關(guān)及其優(yōu)缺點(diǎn)
最近在學(xué)習(xí)有關(guān) AJAX 的知識(shí),上網(wǎng)查閱了一些有關(guān) AJAX 的資料,主要是有關(guān) AJAX的技術(shù)簡(jiǎn)介及其優(yōu)缺點(diǎn)等。在這里,我想對(duì)我收集的資料做一些小小的總結(jié),大部分資料都來(lái)自網(wǎng)上,本人在此只做分類(lèi)總結(jié),希望對(duì)和我一樣正在學(xué)習(xí) AJAX 的朋友有一定的幫助。2015-06-06
編寫(xiě)輕量ajax組件第三篇實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了輕量ajax組件編寫(xiě)第三篇實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04
herf=#導(dǎo)致Ajax請(qǐng)求時(shí)沒(méi)有向后臺(tái)發(fā)送數(shù)據(jù)
當(dāng)點(diǎn)擊重命名進(jìn)行Ajax請(qǐng)求時(shí),并沒(méi)有向后臺(tái)發(fā)送數(shù)據(jù)而是直接跳轉(zhuǎn)到了首頁(yè),后來(lái)發(fā)現(xiàn)是這個(gè)herf=#惹的禍2014-05-05

