表單驗證是前端高頻剛需,但重複造輪子既低效又易漏洞。本文從零構建一個聲明式(DSL 風格)、可擴展、整合驗證流程的輕量框架,核心代碼不足 100 行,適合學習架構思想與實戰復用。
function Field(params) {
this.field_id = params.fid; // 目標 input id
this.validators = params.val; // 驗證器實例陣列
this.on_suc = params.suc; // 成功回調
this.on_error = params.err; // 失敗回調
this.checked = false; // 驗證狀態
}
Field.prototype.validate = function() {
for (let validator of this.validators) {
this.set_callback(validator);
if (!validator.validate(this.data())) break; // 短路機制
}
};
Field.prototype.data = function() {
return document.getElementById(this.field_id).value;
};
Field.prototype.set_callback = function(validator) {
const self = this;
validator.on_suc = function() {
self.checked = true;
self.on_suc(validator.tips);
};
validator.on_error = function() {
self.checked = false;
self.on_error(validator.tips);
};
};
// 1. 長度驗證(含必填)
function Len_val(min, max, tip) {
this.min_v = min; this.max_v = max; this.tips = tip;
}
Len_val.prototype.validate = function(val) {
if (val.length < this.min_v || val.length > this.max_v) {
this.on_error(); return false;
}
this.on_suc(); return true;
};
// 2. 正則表達式驗證
function Exp_val(regex, tip) {
this.exps = regex; this.tips = tip;
}
Exp_val.prototype.validate = function(val) {
if (!val) { this.on_suc(); return true; } // 非必填空值視為通過
if (this.exps.test(val)) { this.on_suc(); return true; }
this.on_error(); return false;
};
// 3. 遠程 AJAX 驗證(依賴 jQuery)
function Remote_val(url, tip) {
this.p_url = url; this.tips = tip;
}
Remote_val.prototype.validate = function(val) {
const self = this;
$.post(this.p_url, { f: val }, function(data) {
if (data.rs) self.on_suc(); else self.on_error();
});
return true; // 異步驗證不阻塞流程,由回調控制最終狀態
};
// 4. 自定義函數驗證(擴展點)
function Custom_val(fn, tip) {
this.fn = fn; this.tips = tip;
}
Custom_val.prototype.validate = function(val) {
const result = this.fn(val);
if (result) this.on_suc(); else this.on_error();
return result;
};
// 實例化字段
const usernameField = new Field({
fid: 'username',
val: [
new Len_val(3, 16, '用戶名長度 3-16 位'),
new Exp_val(/^[a-zA-Z0-9_]+$/, '僅支援字母數字下劃線'),
new Remote_val('/api/check-username', '用戶名已存在')
],
suc: (tip) => showSuccess('username', tip),
err: (tip) => showError('username', tip)
});
// 統一驗證入口
function validateForm() {
const fields = [usernameField, emailField, passwordField];
let allValid = true;
fields.forEach(f => {
f.validate();
if (!f.checked) allValid = false;
});
return allValid;
}
// 表單提交綁定
document.getElementById('myForm').addEventListener('submit', e => {
if (!validateForm()) e.preventDefault();
});
Promise 統一異步流程控制validity) 作為基線這個微框架展示了「小而美」的庫設計哲學:做一件事,做透徹,留足擴展縫隙。 歡迎 Fork 迭代出適合你團隊的版本!