javascript設計模式二: 策略模式
阿新 • • 發佈:2018-12-12
31 32//為元素同時設定多個屬性方法 33var setAttributes = function(el, attrs){ 34 for(var key in attrs){ 35 el.setAttribute(key, attrs[key]) 36 } 37} 38 39//策略類 40var strategiesObj = { 41 isNonEmpty: function(name, value, errorMsg){ 42 if(value === ''){ 43 var errObj = {errName: name, errValue : value, errMsg: errorMsg} 44 return errObj 45 } 46 }, 47 minLength: function(name, value, length, errorMsg){ 48 if(value.length < length){ 49 var errObj = {errName: name, errValue: value, errLength: length, errMsg: errorMsg} 50 return errObj 51 } 52 }, 53 isMobile: function(name, value, errorMsg){ 54 if(!/^1[3|4|5|7|8][0-9]{9}$/.test(value)){ 55 var errObj = {errName: name, errValue: value, errMsg: errorMsg} 56 return errObj 57 } 58 } 59} 60 61//Context類 62var Validator = function(){ 63 this .cache = []; //儲存校驗規則 64 this.errArr = []; 65} 66 67Validator.prototype.add = function(name, dom, rules){ 68 var self = this; 69 for(var i=0, rule; rule=rules[i++];){ 70 (function(rule){ 71 var strategyAry = rule.strategy.split(':'); //把strategy和rule分隔開 72 self.cache.push(function(){ //把校驗的步驟用空函式包裹起來,並且放入cache中, 73 var strategy = strategyAry.shift(strategyAry); //使用者選擇的strategy shift()方法是刪除陣列第一個元素,並返回第一個元素的值 74 strategyAry.unshift(name) 75 strategyAry.splice(1, 0, dom.value) //把input的value新增進引數列表 unshift()方法是向陣列的頭部新增元素,並返回新陣列的長度 76 strategyAry.push(rule.errorMsg) //把errorMsg新增進引數列表 77 return strategiesObj[strategy].apply(null, strategyAry) 78 }) 79 })(rule) 80 } 81} 82 83Validator.prototype.start = function(){ 84 var msgArr = []; 85 var msgObj = {}; 86 for(var i=0; this.cache[i]; i++){ //此處的this.cache[i]函式是在this.cache陣列中儲存的校驗規則函式 87 var resultArgs = this.cache[i](); //開始校驗,並取得校驗後返回資訊 88 if(resultArgs){ //如果有確切的返回值,說明校驗沒有通過 89 msgArr.push({ //將策略類具體方法的返回值組合成陣列物件,包含錯誤表單的索引、name、value、錯誤資訊及其他自定義配置資訊如長度 90 errIndex:i, 91 errName: resultArgs.errName, 92 errValue: resultArgs.errValue, 93 errMsg: resultArgs.errMsg, 94 errLength: resultArgs.errLength?resultArgs.errLength:'' 95 }) 96 } 97 } 98 this.errArr = msgArr; 99 return msgArr100}101102Validator.prototype.errShow = (function(){103 var singleErr = null;104105 return function(){106 console.log(singleErr);107 if(!singleErr){108 for(var i=0, l=this.errArr.length; i<l; i++){109 var label = document.createElement('label')110 label.innerHTML = this.errArr[i].errMsg111 setAttributes(label, {112 'for': this.errArr[i].errName,113 'id': this.errArr[i].errName + '-error',114 'class': 'error'115 })116 //原生js插入兄弟節點是方法是獲取父節點然後通過appendChild或者insertBefore方法插入117 document.getElementsByName(this.errArr[i].errName)[0].parentNode.append(label)118 }119 }120 return singleErr = label;121 }122})()123124//例項化Validator類125var ValidatorFunc = function(){126 var validator = new Validator(); //建立一個validator物件127128 //新增一些校驗規則129 validator.add('username', registerForm.username, [{strategy: 'isNonEmpty', errorMsg: '使用者名稱不能為空'}])130 validator.add('password', registerForm.password, [{strategy: 'minLength:6', errorMsg: '密碼長度不能少於6位'}])131 validator.add('phoneNumber', registerForm.phoneNumber, [{strategy: 'isMobile', errorMsg: '手機號碼格式不正確'}, {strategy: 'minLength:11', errorMsg: '手機號長度不能少於11位'}])132133 var errorMsgArr = validator.start(); //獲得校驗結果134 validator.errShow()135 return errorMsgArr; //返回校驗結果136}137138//實際表單校驗呼叫139var registerForm = document.getElementById('registerForm')140registerForm.onsubmit = function(){141 var errorMsgArr = ValidatorFunc(); //如果errorMsg有確切的返回值,說明未通過校驗142 if(errorMsgArr){143 console.log(errorMsgArr);144 return false //阻止表單提交145 }146}147148