js前端設(shè)計(jì)模式優(yōu)化50%表單校驗(yàn)代碼示例
表單校驗(yàn)
背景
假設(shè)我們正在編寫一個(gè)注冊(cè)頁面,在點(diǎn)擊注冊(cè)按鈕之時(shí),有如下幾條校驗(yàn)邏輯:
- 用戶名不能為空
- 密碼長度不能少于6位
- 手機(jī)號(hào)碼必須符合格式
常規(guī)寫法:
const form = document.getElementById('registerForm'); form.onsubmit = function () { if (form.userName.value === '') { alert('用戶名不能為空'); return false; } if (form.password.value.length < 6) { alert('密碼長度不能少于6位'); return false; } if (!/^1[3|5|8][0-9]{9}$/.test(form.phoneNumber.value)) { alert('手機(jī)號(hào)碼格式不正確'); return false; } ... }
這是一種很常見的代碼編寫方式,但它有許多缺點(diǎn):
- onsubmit 函數(shù)比較龐大,包含了很多 if-else 語句,這些語句需要覆蓋所有的校驗(yàn)規(guī)則。
- onsubmit 函數(shù)缺乏彈性,如果增加了一種新的校驗(yàn)規(guī)則,或者想把密碼的長度從6改成8,我們都必須深入 obsubmit 函數(shù)的內(nèi)部實(shí)現(xiàn),這是違反開放-封閉原則的。
- 算法的復(fù)用性差,如果在項(xiàng)目中增加了另外一個(gè)表單,這個(gè)表單也需要進(jìn)行一些類似的校驗(yàn),我們很可能將這些校驗(yàn)邏輯復(fù)制得漫天遍野。
如何避免上述缺陷,更優(yōu)雅地實(shí)現(xiàn)表單校驗(yàn)?zāi)兀?/p>
策略模式介紹
?? 策略模式是一種行為設(shè)計(jì)模式, 它能讓你定義一系列算法, 把它們一個(gè)個(gè)封裝起來, 并使它們可以相互替換。
真實(shí)世界類比
此圖源自 http://www.dbjr.com.cn/article/252304.htm
假如你需要前往機(jī)場(chǎng)。 你可以選擇騎自行車、乘坐大巴或搭出租車。這三種出行策略就是廣義上的“算法”,它們都能讓你從家里出發(fā)到機(jī)場(chǎng)。你無需深入它們的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),如怎么開大巴、公路系統(tǒng)如何確保你家到機(jī)場(chǎng)有通路等。你只需要了解這些策略的各自特點(diǎn):所需要花費(fèi)的時(shí)間與金錢,你就可以根據(jù)預(yù)算和時(shí)間等因素來選擇其中一種策略。
更廣義的“算法”
在實(shí)際開發(fā)中,我們通常會(huì)把算法的含義擴(kuò)散開來,使策略模式也可以用來封裝一系列的“業(yè)務(wù)規(guī)則”。只要這些業(yè)務(wù)規(guī)則指向的目標(biāo)一致,并且可以被替換使用,我們就可以用策略模式來封裝它們。
策略模式的組成
一個(gè)策略模式至少由兩部分組成。
第一個(gè)部分是一組策略類,策略類封裝了具體的算法,并負(fù)責(zé)具體的計(jì)算過程。
第二個(gè)部分是環(huán)境類 Context,Context 接受客戶的請(qǐng)求,隨后把請(qǐng)求委托給某一個(gè)策略類。
利用策略模式改寫
定義規(guī)則(策略),封裝表單校驗(yàn)邏輯:
const strategies = { isNonEmpty: function (value, errMsg) { if (value === '') { return errMsg; } }, minLenth: function (value, length, errMsg) { if (value.length < length) { return errMsg; } }, isMobile: function (value, errMsg) { if (!/^1[3|5|8][0-9]{9}$/.test(value)) { return errMsg; } } }
定義環(huán)境類 Context,進(jìn)行表單校驗(yàn),調(diào)用策略:
form.onsubmit = function () { const validator = new Validator(); validator.add(form.userName, 'isNonEmpty', '用戶名不能為空'); validator.add(form.password, 'minLength:6', '密碼長度不能少于6位'); validator.add(form.phoneNumber, 'isMobile', '手機(jī)號(hào)碼格式不正確'); const errMsg = validator.start(); if (errMsg) { alert(errMsg); return false; } }
Validator 類代碼如下:
class Validator { constructor() { this.cache = []; } add(dom, rule, errMsg) { const arr = rule.split(':'); this.cache.push(() => { const strategy = arr.shift(); arr.unshift(dom.value); arr.push(errMsg); return strategies[strategy].apply(dom, arr); }) } start() { for (let i = 0; i < this.cache.length; i++) { const msg = this.cache[i](); if (msg) return msg; } } }
使用策略模式重構(gòu)代碼之后,我們消除了原程序中大片的條件分支語句。我們僅僅通過“配置”的方式就可以完成一個(gè)表單校驗(yàn),這些校驗(yàn)規(guī)則也能在程序中任何地方復(fù)用,還能作為插件的形式,方便地移植到其他項(xiàng)目中。
策略模式優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 可以有效地避免多重條件選擇語句。
- 對(duì)開放-封閉原則完美支持,將算法封裝在獨(dú)立的 strategy 中,使得它們易于切換,易于理解,易于擴(kuò)展。
- 可以使算法復(fù)用在系統(tǒng)的其他地方,避免許多重復(fù)的復(fù)制粘貼工作。
缺點(diǎn):
- 使用策略模式會(huì)在程序中增加許多策略類或策略對(duì)象
- 要使用策略模式,必須了解所有的 strategy,了解它們的不同點(diǎn),我們才能選擇一個(gè)合適的 strategy。這是違反最少知識(shí)原則的。
策略模式適合應(yīng)用場(chǎng)景
?? 當(dāng)你想使用對(duì)象中各種不同的算法變體, 并希望能在運(yùn)行時(shí)切換算法時(shí), 可使用策略模式。
策略模式讓你能夠?qū)?duì)象關(guān)聯(lián)至可以不同方式執(zhí)行特定子任務(wù)的不同子對(duì)象, 從而以間接方式在運(yùn)行時(shí)更改對(duì)象行為。
?? 當(dāng)你有許多僅在執(zhí)行某些行為時(shí)略有不同的相似類時(shí), 可使用策略模式。
策略模式讓你能將不同行為抽取到一個(gè)獨(dú)立類層次結(jié)構(gòu)中, 并將原始類組合成同一個(gè), 從而減少重復(fù)代碼。
?? 如果算法在上下文的邏輯中不是特別重要, 使用該模式能將類的業(yè)務(wù)邏輯與其算法實(shí)現(xiàn)細(xì)節(jié)隔離開來。
策略模式讓你能將各種算法的代碼、 內(nèi)部數(shù)據(jù)和依賴關(guān)系與其他代碼隔離開來。 不同客戶端可通過一個(gè)簡(jiǎn)單接口執(zhí)行算法, 并能在運(yùn)行時(shí)進(jìn)行切換。
?? 當(dāng)類中使用了復(fù)雜條件運(yùn)算符以在同一算法的不同變體中切換時(shí), 可使用該模式。
策略模式將所有繼承自同樣接口的算法抽取到獨(dú)立類中, 因此不再需要條件語句。 原始對(duì)象并不實(shí)現(xiàn)所有算法的變體, 而是將執(zhí)行工作委派給其中的一個(gè)獨(dú)立算法對(duì)象。
總結(jié)
在上述例子中,使用策略模式雖然使得程序中多了許多策略對(duì)象和執(zhí)行策略的代碼。但這些代碼可以在應(yīng)用中任意位置的表單復(fù)用,使得整個(gè)程序代碼量大幅減少,且易維護(hù)。下次面對(duì)多表單校驗(yàn)的需求時(shí),別再傻傻寫一堆 if-else 邏輯啦,快試試策略模式!
參考
《JavaScript 設(shè)計(jì)模式與開發(fā)實(shí)踐》——曾探
更多關(guān)于js前端設(shè)計(jì)模式優(yōu)化表單校驗(yàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序 使用騰訊地圖SDK詳解及實(shí)現(xiàn)步驟
這篇文章主要介紹了微信小程序 使用騰訊地圖SDK詳解及實(shí)現(xiàn)步驟的相關(guān)資料,需要的朋友可以參考下2017-02-02自定義range?sliders滑塊實(shí)現(xiàn)元素拖動(dòng)方法
這篇文章主要為大家介紹了自定義range?sliders滑塊實(shí)現(xiàn)元素拖動(dòng)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08微信公眾號(hào) 提示:Unauthorized API function 問題解決方法
這篇文章主要介紹了微信公眾號(hào) 提示:Unauthorized API function 問題解決方法的相關(guān)資料,這里提供了出現(xiàn)提示的解決方法,需要的朋友可以參考下2016-12-12JSON stringify及parse方法實(shí)現(xiàn)數(shù)據(jù)深拷貝
這篇文章主要為大家介紹了JSON.stringify遞歸及JSON.parse有限狀態(tài)自動(dòng)機(jī)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08AntDesignPro使用electron構(gòu)建桌面應(yīng)用示例詳解
這篇文章主要為大家介紹了AntDesignPro使用electron構(gòu)建桌面應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10