同步表單校驗的缺點
響應錯誤信息時,需要重新加載整個頁面(雖然有緩存,客戶端仍然需要通過http協議對比每個文件是否有更新,以保持文件最新)
服務器響應錯誤以後,用戶之前所輸入的信息全部丟失了,用戶需要從頭開始填寫(部分浏覽器幫我們緩存了這些數據)
異步校驗表單的初衷
提升用戶體驗
最大化減少網絡請求,減輕服務器壓力
下面我們看一個常見的異步表單校驗(校驗工號在後台是否存在,存在為有效工號)
校驗工號
復制代碼 代碼如下:
var BASE_PATH = '${rc.contextPath}';
var $workerIdInput = $('#workerIdInput');
var $workerIdError = $('#workerIdError');
//標識用戶輸入的工號是否正確
var isWorkerIdCorrect = false;
var ERROR_WORKER_ID_IS_NULL = "員工工號不能為空";
var ERROR_WORKER_ID_IS_NOT_CORRECT = "請輸入有效的員工工號";
//顯示錯誤信息
function showWorkerIdError(errorMessage) {
$workerIdError.html(errorMessage);
$workerIdError.show();
}
//隱藏錯誤信息
$workerIdInput.on('keydown', function() {
$workerIdError.hide();
});
//將上次輸入的工號保存起來
$workerIdInput.on('focus', function() {
var workerId = $.trim($(this).val());
$(this).data('before', workerId);
});
//blur時進行校驗
$workerIdInput.on('blur', function() {
var workerId = $.trim($(this).val());
//長度為0時,顯示工號為空的錯誤信息
if (!workerId.length) {
showWorkerIdError(ERROR_WORKER_ID_IS_NULL);
return false;
}
//若用戶當前輸入的數據和上次輸入的數據一樣,則不調用後台接口
//假設用戶輸入123456,調用後台接口,返回結果為,不正確的工號
//用戶將輸入內容進行更改後,仍然為123456,則校驗程序不會訪問網絡,直接顯示錯誤信息
if (workerId == $(this).data('before')) {
if (!isWorkerIdCorrect) {
showWorkerIdError(ERROR_WORKER_ID_IS_NOT_CORRECT);
}
return false;
}
//調用後台接口,查詢此員工id是否正確
checkWorkerIdExists(workerId, function(data) {
isWorkerIdCorrect = data.isWorkerIdExists;
if (!isWorkerIdCorrect) {
showWorkerIdError(ERROR_WORKER_ID_IS_NOT_CORRECT);
}
});
});
function checkWorkerIdExists(workerId, callback) {
$.ajax({
url: BASE_PATH + '/forgotPwd/checkWorkerIdExists.htm',
data: {
workerId: workerId
},
success: callback
});
}
$workerIdForm.on('submit', function() {
//只有服務器返回為true的時候,我們的表單才能提交
if (!isWorkerIdCorrect) {
$workerIdInput.focus();
return false;
}
});
上述代碼寫完,一個輸入框的驗證基本上搞定了。
我覺得還有影響用戶體驗的地方
還不支持回車操作,oh my god,回車也要能提交表單
若用戶網速較慢,點擊提交按鈕,會沒有任何反映,因為isWorkerIdCorrect為false,只有服務器校驗成功才為true
下面是修改後的代碼:
復制代碼 代碼如下:
var BASE_PATH = '${rc.contextPath}';
var $workerIdInput = $('#workerIdInput');
var $workerIdError = $('#workerIdError');
//標識用戶輸入的工號是否正確
var isWorkerIdCorrect = false;
//標識後台校驗工號是否已完成(true: 為校驗中, false: 校驗沒開始或已結束)
var isWorkerIdLoading = false;
//標識用戶是否提交了表單
var isSubmit = false;
var ERROR_WORKER_ID_IS_NULL = "員工工號不能為空";
var ERROR_WORKER_ID_IS_NOT_CORRECT = "請輸入有效的員工工號";
//顯示錯誤信息
function showWorkerIdError(errorMessage) {
$workerIdError.html(errorMessage);
$workerIdError.show();
}
//隱藏錯誤信息
$workerIdInput.on('keydown', function() {
$workerIdError.hide();
});
//將上次輸入的工號保存起來
$workerIdInput.on('focus', function() {
var workerId = $.trim($(this).val());
$(this).data('before', workerId);
});
//blur時進行校驗
$workerIdInput.on('blur', function() {
var workerId = $.trim($(this).val());
//長度為0時,顯示工號為空的錯誤信息
if (!workerId.length) {
showWorkerIdError(ERROR_WORKER_ID_IS_NULL);
return false;
}
//若用戶當前輸入的數據和上次輸入的數據一樣,則不調用後台接口
//假設用戶輸入123456,調用後台接口,返回結果為,不正確的工號
//用戶將輸入內容進行更改後,仍然為123456,則校驗程序不會訪問網絡,直接顯示錯誤信息
if (workerId == $(this).data('before')) {
if (!isWorkerIdCorrect) {
showWorkerIdError(ERROR_WORKER_ID_IS_NOT_CORRECT);
}
return false;
}
//調用後台接口,查詢此員工id是否存在
checkWorkerIdExists(workerId, function(data) {
isWorkerIdCorrect = data.isWorkerIdExists;
if (!isWorkerIdCorrect) {
showWorkerIdError(ERROR_WORKER_ID_IS_NOT_CORRECT);
}
});
});
function checkWorkerIdExists(workerId, callback) {
$.ajax({
url: BASE_PATH + '/forgotPwd/checkWorkerIdExists.htm',
data: {
workerId: workerId
},
beforeSend: function() {
//發送請求前,標識正在校驗工號
isWorkerIdLoading = true;
},
success: callback,
complete: function() {
//結束後,關閉標識
isWorkerIdLoading = false;
//在後台校驗數據過程中,用戶若提交了表單,則在此自動提交
if (isSubmit) {
$workerIdForm.submit();
}
}
});
}
//回車提交表單
$workerIdInput.on('keypress', function(e) {
if (e.which === 13) {
$(this).blur();
$workerIdForm.submit();
}
});
$workerIdForm.on('submit', function() {
//若正在後台校驗工號,則標識用戶提交了表單
if (isWorkerIdLoading) {
isSubmit = true;
return false;
}
if (!isWorkerIdCorrect) {
$workerIdInput.focus();
return false;
}
});
最終效果,圖中2個輸入框均為異步校驗,但效果看起來和同步的一樣。
圖中使用了gprs網絡模擬網速較慢的情況
效果圖