如何使用JavaScript策略模式校驗(yàn)表單
概述
Web項(xiàng)目中,登錄,注冊(cè)等等功能都需要表單提交,當(dāng)把用戶的數(shù)據(jù)提交給后臺(tái)之前,前端一般要做一些力所能及的校驗(yàn),比如是否填寫(xiě),填寫(xiě)的長(zhǎng)度,密碼是否符合規(guī)范等等,前端校驗(yàn)可以避免提交不合規(guī)范的表單。
假如我們有一個(gè)表單,校驗(yàn)邏輯如下:
- 用戶名不為空
- 密碼長(zhǎng)度不低于6位
- 手機(jī)號(hào)符合格式
未使用策略模式的表單校驗(yàn)
當(dāng)沒(méi)有使用策略模式時(shí),即我們首先會(huì)想到的校驗(yàn)?zāi)J酵ǔJ沁@樣的:
<body>
<form id="registerForm">
<label for="username">輸入用戶名:<input type="text" name="username"></label>
<label for="password">輸入密碼:<input type="password" name="password"></label>
<label for="phone">輸入密碼:<input type="text" name="phone"></label>
</form>
<script>
const form = document.querySelector('.registerForm');
form.onsubmit = function(){
if(form.username.value === ''){
alert('用戶名不能為空')
return;
}
if(form.password.value.length < 6){
alert('密碼長(zhǎng)度不能小于6位')
return;
}
if(!/(^1[3|5|8][0-9]{9}$)/.test(form.phone.value)){
alert('手機(jī)號(hào)格式不正確')
return;
}
}
</script>
</body>
這種代碼編寫(xiě)方式十分常見(jiàn),但它的缺點(diǎn)同樣很明顯:
- onsubmit函數(shù)過(guò)于龐大,包含很多if-else,要覆蓋所有規(guī)則
- onsubmit函數(shù)缺乏彈性,如果要進(jìn)入一種新的校驗(yàn)規(guī)則,就要改函數(shù)的內(nèi)容實(shí)現(xiàn),違反開(kāi)放-閉合原則
- 代碼復(fù)用性較差,如果再寫(xiě)一個(gè)表單,就要復(fù)制很多重復(fù)的代碼
使用策略模式優(yōu)化
首先封裝校驗(yàn)函數(shù)為一個(gè)對(duì)象:
const strategies = {
empty(value, errMsg){
if(value.length === 0){
return errMsg;
}
},
minLength(value, len, errMsg){
if(value.length < len){
return errMsg;
}
},
isMobile(value, errMsg){
if(!/(^1[3|5|8][0-9]{9}$)/.test(value)){
return errMsg;
}
}
}
我們還要一個(gè)Validator類, 這個(gè)類用于向目標(biāo)表單添加驗(yàn)證規(guī)則,它的用法如下:
const validate = function(){
const validator = new Validator();
validator.add(Form.userName, 'empty', '用戶名不能為空');
validator.add(Form.password, 'minLength:6', '密碼長(zhǎng)度不能少于6位');
validator.add(Form.phone, 'isMobile', '手機(jī)號(hào)碼格式不正確');
const errMsg = validator.start();
return errMsg;
}
如代碼所示,validator實(shí)例有add方法,接收3個(gè)參數(shù),第一個(gè)為需要驗(yàn)證的表單實(shí)例,第二個(gè)為驗(yàn)證方法,冒號(hào)后面為傳入的參數(shù)。第三個(gè)為驗(yàn)證未通過(guò)的錯(cuò)誤提示信息。
start方法,用于啟動(dòng)校驗(yàn),如果沒(méi)通過(guò)會(huì)返回未通過(guò)的提示信息,可在之后的邏輯中進(jìn)行處理
Validator類的編寫(xiě):
class Validator {
constructor(){
this.rules = [];
}
add(elem, rule, err){
const args_arr = rule.split(":");
this.rules.push(()=>{
const handler = args_arr.shift();
args_arr.unshift(elem.value);
args_arr.push(err);
return strategies[handler].apply(elem, args_arr)
})
}
start(){
let errmsg = []
for(let i = 0; i < this.rules.length; i++ ){
const err = this.rules[i]();
if(err){
errmsg.push(err)
}
}
return errmsg.join(",");
}
}
使用策略模式,我們使用配置的方式完成了表單的校驗(yàn),這些規(guī)則可以用在以后任何校驗(yàn)表單的地方,更方便修改與復(fù)用
為單一表單項(xiàng)增加多個(gè)驗(yàn)證規(guī)則
我們的代碼現(xiàn)在有一個(gè)缺點(diǎn),就是只能為某一個(gè)表單項(xiàng)賦單一驗(yàn)證規(guī)則,無(wú)法實(shí)現(xiàn)一個(gè)表單多個(gè)驗(yàn)證規(guī)則,所以代碼還有優(yōu)化的空間
class Validator{
// ···
add(elem, rules){
rules.forEach(rule => {
const args_arr = rule.strategy.split(":");
this.rules.push(()=>{
const handler = args_arr.shift();
args_arr.unshift(elem.value);
args_arr.push(rule.errMsg);
return strategies[handler].apply(elem, args_arr)
})
});
}
// ···
}
const validate = function(){
const validator = new Validator();
validator.add(Form.username,[{
strategy: 'empty',
errMsg: '用戶名不能為空'
}]);
validator.add(Form.password, [{
strategy: 'minLength:6',
errMsg: '密碼長(zhǎng)度不能少于6位'
}]);
validator.add(Form.phone, [{
strategy: 'isMobile',
errMsg: '手機(jī)號(hào)碼格式不正確'
}, {
strategy: 'empty',
errMsg: '手機(jī)號(hào)不能為空'
}]);
const errMsg = validator.start();
return errMsg;
}
只需要傳參時(shí)傳入一個(gè)對(duì)象數(shù)組,并在add函數(shù)里面添加相應(yīng)的數(shù)組處理邏輯即可
策略模式的優(yōu)點(diǎn)
優(yōu)點(diǎn):
- 避免多重條件選擇語(yǔ)句
- 實(shí)現(xiàn)開(kāi)閉原則,使得函數(shù)的使用更加易于切換,易于理解,易于擴(kuò)展。
- 提高代碼復(fù)用程度
總結(jié)
Peter Norvig說(shuō)過(guò),在函數(shù)作為一等對(duì)象的語(yǔ)言中,策略模式是隱形,strategy就是值為函數(shù)的變量。其實(shí)就是將封裝好的策略函數(shù)當(dāng)成參數(shù)傳給使用它的target,被target調(diào)用的過(guò)程,用好策略模式,不僅讓我們對(duì)該模式有更加深刻的理解,也使我們明白使用函數(shù)的好處。
以上就是如何使用JavaScript策略模式校驗(yàn)表單的詳細(xì)內(nèi)容,更多關(guān)于JavaScript資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序中插入激勵(lì)視頻廣告并獲取收益(實(shí)例代碼)
這篇文章主要介紹了微信小程序中插入激勵(lì)視頻廣告并獲取收益,通過(guò)代碼給大家介紹了如何插入及注意事項(xiàng),需要的朋友可以參考下2019-12-12
JS實(shí)現(xiàn)給不同元素設(shè)置不同的定時(shí)器
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)給不同元素設(shè)置不同的定時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
JS表示Stack類練習(xí)用棧實(shí)現(xiàn)任意進(jìn)制轉(zhuǎn)換
這篇文章主要為大家介紹了JS表示Stack類練習(xí)用棧實(shí)現(xiàn)任意進(jìn)制轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
鼠標(biāo)右擊事件代碼(asp.net后臺(tái))
本程序由一個(gè)js文件和aspx文件組成,沒(méi)有后臺(tái)CS代碼。2011-01-01
詳解ES6通過(guò)WeakMap解決內(nèi)存泄漏問(wèn)題
本篇文章主要介紹了詳解ES6通過(guò)WeakMap解決內(nèi)存泄漏問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
微信企業(yè)號(hào)開(kāi)發(fā)之微信考勤百度地圖定位
本文給大家介紹微信企業(yè)號(hào)開(kāi)發(fā)之微信考勤百度地圖定位,有需要的朋友參考下本篇文章2015-09-09

