亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

利用策略模式與裝飾模式擴展JavaScript表單驗證功能

2019-11-19 17:35:16
字體:
來源:轉載
供稿:網友

簡單的表單驗證

html結構

<!-- validata.html --><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Validata</title></head><body> <form id="form"> <label for="username">賬號:</label><input id="username" type="text"><br> <label for="password">密碼:</label><input id="password" type="password"><br> <label for="phonenum">手機:</label><input id="phonenum" type="text"><br> <input id="submit" type="button" value="提交"> </form> <p id="warn"></p> <script src="validata.js"></script></body></html>

首先先簡單地實現以下這個功能

之后再用設計模式豐滿

// validata.jsvar form = document.getElementById('form'), warn = document.getElementById('warn');var validata = function(){ if(form.username.value === ''){ return warn.textContent = '賬號不能為空'; } if(form.password.value === ''){ return warn.textContent = '密碼不能為空'; } if(form.phonenum.value === ''){ return warn.textContent = '手機號不能為空'; } var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); ajax提交數據略 return warn.textContent = '用戶信息已成功提交至服務器';}form.submit.onclick = function(){ validata();}

然后分析以下代碼

validata這個函數毫無復用性可言,除此之外存在兩個問題

  • 函數同時承擔了驗證和提交兩個職責,違背單一職責原則
  • 驗證功能擴展性差,要想添加驗證規則就必須深入函數內部,違反開放-封閉原則

所以我們需要對此進行改進

裝飾模式重構

先來用裝飾模式解決一下函數多職責問題

方法也很簡單

改進一下AOP前置裝飾函數(Function.prototype.before)

當擴展函數(beforeFn)返回false則不執行當前函數

然后令表單驗證函數成為表單提交函數的前置裝飾

這樣提交前就會進行驗證,若驗證失敗,就不會提交數據

var form = document.getElementById('form'), warn = document.getElementById('warn');Function.prototype.before = function(beforeFn){ var self = this; return function(){ if(beforeFn.apply(this, arguments) === false)  return; return self.apply(this, arguments); }}//改進的AOP前置裝飾函數var validata = function(){ if(form.username.value === ''){ warn.textContent = '賬號不能為空'; return false; } if(form.password.value === ''){ warn.textContent = '密碼不能為空'; return false; } if(form.phonenum.value === ''){ warn.textContent = '手機號不能為空'; return false; }}var submitMsg = function(){ //將提交的功能從validata函數中提取出來 var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); return warn.textContent = '用戶信息已成功提交至服務器';}submitMsg = submitMsg.before(validata);//讓表單驗證函數成為表單提交函數的裝飾者form.submit.onclick = function(){ submitMsg();};

策略模式重構

下面就該解決函數缺乏彈性的問題

使用策略模式就需要有策略對象/類和環境對象/類

毫無疑問策略對象中就應該裝著校驗規則

又考慮到頁面可能不止有一個驗證表單

最好寫成工廠-類的形式

完整代碼如下

var form = document.getElementById('form'), warn = document.getElementById('warn');Function.prototype.before = function(beforeFn){ var self = this; return function(){ if(beforeFn.apply(this, arguments) === false)  return; return self.apply(this, arguments); }}var vldStrategy = { //策略對象-驗證規則 isNonEmpty: function(value, warnMsg){ //輸入不為空 if(value === '')  return warnMsg; }, isLongEnough: function(value, length, warnMsg){ //輸入足夠長 if(value.length < length)  return warnMsg; }, isShortEnough: function(value, length, warnMsg){ //輸入足夠短 if(value.length > length)  return warnMsg; }, isMobile: function(value, warnMsg){ //手機號驗證 var reg = /^1[3|5|8][0-9]{9}$/; if(!reg.test(value))  return warnMsg; }}var Validator = function(){ //環境類 this.rules = []; //數組用于存放負責驗證的函數};Validator.prototype.add = function(domNode, ruleArr){ //添加驗證規則 var self = this; for(var i = 0, rule; rule = ruleArr[i++];){ (function(rule){  var strategyArr = rule.strategy.split(':'),   warnMsg = rule.warnMsg;  self.rules.push(function(){  var tempArr = strategyArr.concat();  var ruleName = tempArr.shift();  tempArr.unshift(domNode.value);  tempArr.push(warnMsg);  return vldStrategy[ruleName].apply(domNode, tempArr);  }); })(rule); } return this;};Validator.prototype.start = function(){ //開始驗證表單 for(var i = 0, vldFn; vldFn = this.rules[i++];){ var warnMsg = vldFn(); if(warnMsg){  warn.textContent = warnMsg;  return false; } }}var vld = new Validator();vld.add(form.username, [ { strategy: 'isNonEmpty', warnMsg: '賬號不能為空' }, { strategy: 'isLongEnough:4', warnMsg: '賬號不能小于4位' }, { strategy: 'isShortEnough:20', warnMsg: '賬號不能大于20位' }]).add(form.password, [ { strategy: 'isNonEmpty', warnMsg: '密碼不能為空' }]).add(form.phonenum, [ { strategy: 'isNonEmpty', warnMsg: '手機號不能為空' }, { strategy: 'isMobile', warnMsg: '手機號格式不正確' }]);var submitMsg = function(){ var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); return warn.textContent = '用戶信息已成功提交至服務器';}submitMsg = submitMsg.before(vld.start.bind(vld));form.submit.onclick = function(){ submitMsg();};//這里只是模擬提交,實際應該用form.onsubmit

問題分析

總結一下易錯的地方還有我敲得時候遇到的問題

Validator.prototype.add = function(domNode, ruleArr){ var self = this; for(var i = 0, rule; rule = ruleArr[i++];){ (function(rule){  var strategyArr = rule.strategy.split(':'),   warnMsg = rule.warnMsg;  self.rules.push(function(){  var tempArr = strategyArr.concat();  var ruleName = tempArr.shift();  tempArr.unshift(domNode.value);  tempArr.push(warnMsg);  return vldStrategy[ruleName].apply(domNode, tempArr);  }); })(rule); } return this;};

在Validator原型鏈上的add函數需要注意幾個問題

首先添加IIFE立即執行函數解決閉包問題就不用多說了

函數內又嵌套了函數,導致了this被劫持,所以必須緩存this

var self = this;

最開始我沒有拷貝這個數組而是直接使用的strategyArr

Validator.prototype.add = function(domNode, ruleArr){ //添加驗證規則 var self = this; for(var i = 0, rule; rule = ruleArr[i++];){ (function(rule){  var strategyArr = rule.strategy.split(':'),   warnMsg = rule.warnMsg;  self.rules.push(function(){  // var tempArr = strategyArr.concat();  var ruleName = strategyArr.shift();  strategyArr.unshift(domNode.value);  strategyArr.push(warnMsg);  return vldStrategy[ruleName].apply(domNode, strategyArr);  }); })(rule); } return this;};

第一次提交沒有問題,但再次提交就會報錯

這是因為第一次提交后,閉包中的strategyArr已經改變

之后的提交,對這個數組進行操作就不是預期的結果了

在這個地方我犯了一個小錯誤,導致我斷點調試了好長時間 __亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

久久99视频精品| 粗暴蹂躏中文一区二区三区| 91探花福利精品国产自产在线| 久久综合网hezyo| 欧美资源在线观看| 热门国产精品亚洲第一区在线| 北条麻妃99精品青青久久| 美女视频黄免费的亚洲男人天堂| 疯狂蹂躏欧美一区二区精品| 国产日韩换脸av一区在线观看| 在线日韩第一页| 中文字幕日韩在线播放| 亚洲精品第一页| 欧美日韩国产专区| 国产91色在线|免| 狠狠操狠狠色综合网| 亚洲国产精品福利| 久久久www成人免费精品张筱雨| 亚洲欧洲午夜一线一品| 亚洲自拍小视频| 久久免费成人精品视频| 5278欧美一区二区三区| 亚洲毛茸茸少妇高潮呻吟| 国产精品久久国产精品99gif| 亚洲经典中文字幕| 国产一区二区三区在线| 国产成人av在线播放| 国产精品视频一| 国产91精品久| 久久国产精品首页| 欧美另类老女人| 久久久成人精品视频| 亚洲www永久成人夜色| 欧美国产在线视频| 国产亚洲福利一区| 91九色单男在线观看| 777精品视频| 亚洲欧洲偷拍精品| 亚洲天堂网站在线观看视频| 色哟哟亚洲精品一区二区| 一区二区亚洲精品国产| 乱亲女秽乱长久久久| 国产精品免费在线免费| 亚洲成人激情小说| 色yeye香蕉凹凸一区二区av| 狠狠躁天天躁日日躁欧美| 久久久爽爽爽美女图片| 欧美日韩亚洲精品内裤| 欧美激情视频网址| 欧美性猛交xxxx富婆| 国产一区二区三区中文| 国产成人精品免高潮费视频| 97碰在线观看| 亚洲精品自拍第一页| 中文字幕成人精品久久不卡| 免费91麻豆精品国产自产在线观看| 欧美xxxx18性欧美| 国产日韩精品在线| 国产在线视频不卡| 国产精品草莓在线免费观看| 亚洲小视频在线观看| 国产精品久久久久av免费| 亚洲一区亚洲二区| 久久久久一本一区二区青青蜜月| 日韩视频免费大全中文字幕| 亚洲美女在线视频| 欧美最猛性xxxx| 伊人伊人伊人久久| 亚洲自拍偷拍色图| 91精品国产成人| 亚洲男女自偷自拍图片另类| 视频在线观看一区二区| 国产suv精品一区二区三区88区| 日韩亚洲一区二区| 少妇高潮久久久久久潘金莲| 欧美肥臀大乳一区二区免费视频| 中文字幕日韩精品在线| 亚洲色图第三页| 在线观看精品自拍私拍| 精品国产91乱高清在线观看| 欧美性高跟鞋xxxxhd| 国产区精品视频| 亚洲欧美三级在线| yellow中文字幕久久| 久久中文字幕国产| 成人免费视频在线观看超级碰| 国产成人精品一区二区在线| 欧美最猛性xxxxx亚洲精品| 国产精品日韩欧美大师| 亚洲成人激情在线| 日韩成人中文字幕在线观看| 丁香五六月婷婷久久激情| 亚洲最大成人网色| 亚洲女人天堂色在线7777| 欧美成aaa人片免费看| 国产精品jizz在线观看麻豆| 国产精品爽爽爽爽爽爽在线观看| 亚洲精品ady| 最近2019中文字幕第三页视频| 亚洲第一综合天堂另类专| 国产精品一区二区女厕厕| 日韩有码片在线观看| 日韩欧美在线一区| 国产成人精彩在线视频九色| 欧洲美女7788成人免费视频| 日韩视频在线免费观看| 亚洲精品乱码久久久久久按摩观| 国产婷婷成人久久av免费高清| 这里精品视频免费| 最近2019中文免费高清视频观看www99| 欧美国产日产韩国视频| 日韩在线播放av| 亚洲欧美日韩区| 欧美在线日韩在线| 国产va免费精品高清在线| 亚洲精品国产精品国产自| 日韩中文字幕视频在线观看| 91日本视频在线| 国产日产久久高清欧美一区| 亚洲最新视频在线| 在线观看91久久久久久| 欧美激情在线有限公司| 日韩精品亚洲视频| 国产成人精品亚洲精品| 91麻豆国产语对白在线观看| 国产精品久久久av久久久| 国产精品狼人色视频一区| 国产91色在线播放| 欧美日韩亚洲成人| 国产精品免费网站| 在线观看免费高清视频97| 欧美激情亚洲视频| 国自产精品手机在线观看视频| 精品国产区一区二区三区在线观看| 日本精品视频在线观看| 国产精品久久久久久av| 欧美床上激情在线观看| 日韩电影中文字幕在线观看| 最近2019年中文视频免费在线观看| 国产精品久久久久久久一区探花| www.日韩.com| 精品国产一区av| 国产suv精品一区二区三区88区| 亚洲日韩第一页| 国产一区二区免费| 久久99精品国产99久久6尤物| 国产97在线|日韩| 欧美黄网免费在线观看| 粉嫩av一区二区三区免费野| 国产日韩欧美另类| 亚洲一区久久久| 日韩欧美在线视频日韩欧美在线视频| 在线观看国产成人av片| 国产精品视频一| 欧美日韩人人澡狠狠躁视频| 国产亚洲欧洲在线| 精品视频久久久久久久| 亚洲iv一区二区三区| 91免费看国产| 国产精品在线看| 成人精品一区二区三区| 亚洲a区在线视频| 夜夜嗨av一区二区三区四区| 亚洲美女视频网|