用策略模式實現(xiàn)表單的校驗

預(yù)覽

GIF.gif

作為一名前端人士,在一個web項目中七芭,注冊、登錄蔑赘、修改用戶信息等功能的實現(xiàn)都離不開表單狸驳。在將用戶輸入的數(shù)據(jù)提交給后臺之前,常常需要做一些客戶端力所能及的校驗工作缩赛。比如注冊的時候需要校驗是否填寫了用戶名耙箍,密碼的長度是否符合規(guī)定,等等酥馍。好了究西,您可能會說,說出你的夢想物喷,開始你的表演卤材,接下來我要開始我的表演了。??
假設(shè)現(xiàn)在我要寫一個注冊頁面峦失,在店家注冊按鈕之前扇丛,有如下幾條校驗邏輯:
用戶名不能為空
密碼長度不能小于6位
手機(jī)號碼必須符合格式

一、表單校驗的第一個版本

<html>
<body>
    <form action="https://www.baidu.com" method="post" id="registerForm">
        請輸入用戶名<input type="text" name="userName"><br> 
        請輸入密碼  <input type="password" name="password"><br> 
        請輸入手機(jī)號碼<input type="text" name="phoneNumber"><br>
        <button>提交</button>
    </form>
</body>
</html>

么有寫CSS樣式尉辑,感覺界面丑哭??帆精,實現(xiàn)功能最重要,對不?

    <script>
        const registerForm = document.getElementById('registerForm');
        registerForm.onsubmit = function() {
            if (registerForm.userName != "") {
                if (registerForm.password.length >= 6) {
                    if (/^1[3|4|5|7|8][0-9]{9}$/.test(registerForm.phoneNumber)) {
                        alert('成功');
                    } else {
                        alert('請輸入正確的的手機(jī)號卓练!');
                        return false;
                    }
                } else {
                    alert('密碼不能小于六位');
                    return false;
                }
            } else {
                alert("用戶名不能為空隘蝎!");
                return false;
            }
        }
    </script>

這是一種最常見的代碼編寫方式,但是他的缺點顯而易見襟企。registerForm.onsubmit函數(shù)比較龐大嘱么,包含了過多的if-else語句,如果增加一條新的校驗規(guī)則顽悼,或者想把免得長度校驗從6位增加到8位曼振,要去registerForm.onsubmit內(nèi)部更改,這樣就違反了開放-封閉的原則蔚龙。

二冰评、用策略模式實現(xiàn)表單的校驗

我們經(jīng)常說,條條大路通羅馬木羹,在現(xiàn)實生活中甲雅,很多時候也有很多途徑到達(dá)同一個目的地。假如我們要去某個地方旅游坑填,我們可以這樣選擇:
不考慮金錢的情況下抛人,為了節(jié)省時間,我們選擇乘坐飛機(jī)
考慮錢的話穷遂,那就火車或者bus
像我這樣的只能來個自行車去旅游了,這就是差距啊??娱据,到此為止蚪黑,我們來說說主角吧,蹬蹬蹬蹬中剩,策略模式來了忌穿。
策略模式就是定義一系列算法,把它們一個個封裝起來结啼,并且是它們可以相互替換掠剑。
用策略模式來實現(xiàn)表單的檢驗,第一步我們先來把這些校驗邏輯封裝成策略對象

  var strategies = {
    // errorMsg參數(shù)郊愧,提升了適用性
    isNonEmpty: function(value, errorMsg) {  //不為空
        if (value === '') {
            // 返回字符串true  錯誤信息
            return errorMsg;
        }
    },
    minLength: function(value, length, errorMsg) { //限制最小長度
        if (value.length < length) {
            return errorMsg;
        }
    },
    isMobile: function(value, errorMsg) {
        if (!/^1[1|5|8|7|4|3][0-9]{9}$/.test(value)) { //電話號碼校驗
            return errorMsg;
        }
    }
}

接下來就是實現(xiàn)Validator類了朴译。Validator負(fù)責(zé)接收用戶的請求并委托給strategy對象。我們先來了解下用戶是如何向Validator類發(fā)送請求的属铁,這有助于我們知道如何去編寫Validator類的代碼眠寿。代碼如下:

        function validateFunc() {
            // 校驗處理 分離出去
            var validator = new Validator(); //創(chuàng)建validator對象
            // 一個個去校驗
            // 數(shù)組 遍歷
            /**********************添加校驗規(guī)則**********************/
            validator.add(registerForm.userName, 'isNonEmpty', '用戶名不能為空');
            validator.add(registerForm.password, 'minLength:6', '密碼長度不能少于6位');
            validator.add(registerForm.phoneNumber, 'isMobile', '手機(jī)號碼格式不正確')
            var errorMsg = validator.start(); //獲取校驗結(jié)果
            // 一個個去校驗
            return errorMsg; //返回校驗結(jié)果
        }
        registerForm.onsubmit = function() {
            // 一票規(guī)則 數(shù)組
            var errorMsg = validateFunc(); //如果errorMsg有確切的返回值,說明校驗未通過焦蘑,即輸入的內(nèi)容不符合規(guī)則
            if (errorMsg) {
                alert(errorMsg);
                return false; //阻止表單提交
            }
        }

通過這段代碼盯拱,我們先創(chuàng)建了一個validator對象,然后通過validator.add方法,往validator對象中添加一些檢驗規(guī)則狡逢。validator.add方法接受三個參數(shù)宁舰,

  validator.add(registerForm.password, 'minLength:6', '密碼長度不能少于6位');

registerForm.password為參與校驗的input輸入框。
'minLength:6'是一個以冒號隔開的字符串奢浑。冒號前面的minLength代表挑選的strategy對象蛮艰,冒號后面的數(shù)字6表示在校驗中過程中所必須的參數(shù)。'minLength:6'的意思是校驗registerForm.password這個文本框輸入的最小長度不能小于6殷费。如果這個字符串中不過不包含冒號印荔,說明教研過程中不需要額外的參數(shù),如'isNonEmpty'&'isMobile'详羡。
第三個參數(shù)是當(dāng)被校驗的值不符合規(guī)則的時仍律,返回的錯誤信息。
在往validator對象里添加了一系列的校驗規(guī)則后实柠,我們就要使用validator.start()方法來啟動校驗水泉。如果validator.start()返回一個確切的errorMsg字符串當(dāng)作返回值,就表明校驗沒有通過窒盐,此時需要registerForm.onsubmit方法返回false來阻止表單的提交草则。
最后實現(xiàn)Validator類:

  var Validator = function() {
    this.cache = [];
}

Validator.prototype.add = function(ele, rule, errorMsg) {
    var arr = rule.split(':');
    this.cache.push(function() {
        // 規(guī)則
        var strategy = arr.shift();
        arr.unshift(ele.value);
        arr.push(errorMsg);
        return strategies[strategy].apply(ele, arr);
    });
}

Validator.prototype.start = function() {
    for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
        var msg = validatorFunc();
        if (msg) {
            return msg;
        }
    }
};

使用策略模式重構(gòu)代碼后,僅僅可以通過“配置”的方式就可以完成一個表單的校驗蟹漓,這些校驗規(guī)則也可以復(fù)用在程序的任何地方炕横,這就是我們所所得,處處適用葡粒。
在修改某個校驗規(guī)則的時候份殿,只需要編寫或者改寫少量的代碼。假如想將用戶名輸入框的校驗規(guī)則修改成用戶名不能少于四個字符嗽交。代碼如下所示:

  validator.add(registerForm.userName, 'isNonEmpty', '用戶名不能為空');
//改成
validator.add(registerForm.userName, 'minLength:8', '用戶名長度不能小于8位');

學(xué)習(xí)中遇到的問題

(1)什么鬼卿嘲?在校驗失敗的情況下,還會實現(xiàn)頁面的跳轉(zhuǎn)夫壁,真的讓人有點受不了拾枣,所以我要說的是,一定要在registerForm.onsubmit方法返回false來阻止表單的提交盒让。
(2)再來解釋下手機(jī)號碼的校驗規(guī)則

      isMobile: function(value, errorMsg) {
        if (!/^1[1|3|4|5|7|8][0-9]{9}$/.test(value)) { //電話號碼校驗
            return errorMsg;
        }
    }

表示第一位只匹配數(shù)字1梅肤,第二位匹配(3|4|5|7|8)里面的任意一個數(shù)值,剩下的9位是沒有限制的邑茄,也就是可以匹配0-9之間的任意數(shù)字凭语,最后以$結(jié)尾。test函數(shù)返回的是一個boolean值撩扒。正則表達(dá)式中 test似扔、exec吨些、match 方法區(qū)別http://www.cnblogs.com/meixianfeng/articles/2762273.html
代碼地址:https://github.com/SiHao24/js_pattern

結(jié)語

策略模式的巧妙之處遠(yuǎn)遠(yuǎn)不止這些炒辉,我只是列舉了其中小小的一個環(huán)節(jié)豪墅!還需要花費更多的時間去學(xué)習(xí)其中的奧秘。雖然開始學(xué)的很艱難黔寇,但是努力過后偶器,就會陶醉在知識的海洋里!
有建議或者覺得有錯誤的地方可以指出來喲,讓我跟隨大佬們的步伐缝裤,繼續(xù)努力吧屏轰!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市憋飞,隨后出現(xiàn)的幾起案子霎苗,更是在濱河造成了極大的恐慌,老刑警劉巖榛做,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唁盏,死亡現(xiàn)場離奇詭異,居然都是意外死亡检眯,警方通過查閱死者的電腦和手機(jī)厘擂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锰瘸,“玉大人刽严,你說我怎么就攤上這事”苣” “怎么了舞萄?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長恕曲。 經(jīng)常有香客問我鹏氧,道長渤涌,這世上最難降的妖魔是什么佩谣? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮实蓬,結(jié)果婚禮上茸俭,老公的妹妹穿的比我還像新娘。我一直安慰自己安皱,他們只是感情好调鬓,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酌伊,像睡著了一般腾窝。 火紅的嫁衣襯著肌膚如雪缀踪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天虹脯,我揣著相機(jī)與錄音驴娃,去河邊找鬼。 笑死循集,一個胖子當(dāng)著我的面吹牛唇敞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咒彤,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼疆柔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镶柱?” 一聲冷哼從身側(cè)響起旷档,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奸例,沒想到半個月后彬犯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡查吊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年谐区,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逻卖。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡宋列,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出评也,到底是詐尸還是另有隱情炼杖,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布盗迟,位于F島的核電站坤邪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏罚缕。R本人自食惡果不足惜艇纺,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邮弹。 院中可真熱鬧黔衡,春花似錦、人聲如沸腌乡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽与纽。三九已至侣签,卻和暖如春塘装,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背影所。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工氢哮, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人型檀。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓冗尤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胀溺。 傳聞我的和親對象是個殘疾皇子裂七,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容