国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

利用策略模式與裝飾模式擴(kuò)展JavaScript表單驗(yàn)證功能

2019-11-19 17:35:16
字體:
供稿:網(wǎng)友

簡單的表單驗(yàn)證

html結(jié)構(gòu)

<!-- 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">手機(jī):</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>

首先先簡單地實(shí)現(xiàn)以下這個功能

之后再用設(shè)計模式豐滿

// 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 = '手機(jī)號不能為空'; } var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); ajax提交數(shù)據(jù)略 return warn.textContent = '用戶信息已成功提交至服務(wù)器';}form.submit.onclick = function(){ validata();}

然后分析以下代碼

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

  • 函數(shù)同時承擔(dān)了驗(yàn)證和提交兩個職責(zé),違背單一職責(zé)原則
  • 驗(yàn)證功能擴(kuò)展性差,要想添加驗(yàn)證規(guī)則就必須深入函數(shù)內(nèi)部,違反開放-封閉原則

所以我們需要對此進(jìn)行改進(jìn)

裝飾模式重構(gòu)

先來用裝飾模式解決一下函數(shù)多職責(zé)問題

方法也很簡單

改進(jìn)一下AOP前置裝飾函數(shù)(Function.prototype.before)

當(dāng)擴(kuò)展函數(shù)(beforeFn)返回false則不執(zhí)行當(dāng)前函數(shù)

然后令表單驗(yàn)證函數(shù)成為表單提交函數(shù)的前置裝飾

這樣提交前就會進(jìn)行驗(yàn)證,若驗(yàn)證失敗,就不會提交數(shù)據(jù)

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); }}//改進(jìn)的AOP前置裝飾函數(shù)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 = '手機(jī)號不能為空'; return false; }}var submitMsg = function(){ //將提交的功能從validata函數(shù)中提取出來 var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); return warn.textContent = '用戶信息已成功提交至服務(wù)器';}submitMsg = submitMsg.before(validata);//讓表單驗(yàn)證函數(shù)成為表單提交函數(shù)的裝飾者form.submit.onclick = function(){ submitMsg();};

策略模式重構(gòu)

下面就該解決函數(shù)缺乏彈性的問題

使用策略模式就需要有策略對象/類和環(huán)境對象/類

毫無疑問策略對象中就應(yīng)該裝著校驗(yàn)規(guī)則

又考慮到頁面可能不止有一個驗(yàn)證表單

最好寫成工廠-類的形式

完整代碼如下

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 = { //策略對象-驗(yàn)證規(guī)則 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){ //手機(jī)號驗(yàn)證 var reg = /^1[3|5|8][0-9]{9}$/; if(!reg.test(value))  return warnMsg; }}var Validator = function(){ //環(huán)境類 this.rules = []; //數(shù)組用于存放負(fù)責(zé)驗(yàn)證的函數(shù)};Validator.prototype.add = function(domNode, ruleArr){ //添加驗(yàn)證規(guī)則 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(){ //開始驗(yàn)證表單 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: '手機(jī)號不能為空' }, { strategy: 'isMobile', warnMsg: '手機(jī)號格式不正確' }]);var submitMsg = function(){ var msg = { username: form.username.value, password: form.password.value, phonenum: form.phonenum.value } //ajax('...', msg); return warn.textContent = '用戶信息已成功提交至服務(wù)器';}submitMsg = submitMsg.before(vld.start.bind(vld));form.submit.onclick = function(){ submitMsg();};//這里只是模擬提交,實(shí)際應(yīng)該用form.onsubmit

問題分析

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

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函數(shù)需要注意幾個問題

首先添加IIFE立即執(zhí)行函數(shù)解決閉包問題就不用多說了

函數(shù)內(nèi)又嵌套了函數(shù),導(dǎo)致了this被劫持,所以必須緩存this

var self = this;

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

Validator.prototype.add = function(domNode, ruleArr){ //添加驗(yàn)證規(guī)則 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;};

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

這是因?yàn)榈谝淮翁峤缓螅]包中的strategyArr已經(jīng)改變

之后的提交,對這個數(shù)組進(jìn)行操作就不是預(yù)期的結(jié)果了

在這個地方我犯了一個小錯誤,導(dǎo)致我斷點(diǎn)調(diào)試了好長時間 __

主站蜘蛛池模板: 河间市| 金溪县| 全南县| 永丰县| 浦城县| 碌曲县| 普兰县| 大荔县| 吉安县| 平陆县| 休宁县| 云霄县| 潢川县| 堆龙德庆县| 措美县| 大名县| 合作市| 吉首市| 阿鲁科尔沁旗| 西城区| 资阳市| 石城县| 健康| 洛阳市| 峨眉山市| 梨树县| 泰和县| 潍坊市| 阿合奇县| 昔阳县| 黄骅市| 河池市| 神农架林区| 巩留县| 铜陵市| 无为县| 城口县| 宿松县| 余姚市| 德钦县| 桓仁|