91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-07-26 09:23:43 來源:億速云 閱讀:213 作者:小新 欄目:web開發

這篇文章主要介紹了如何使用策略模式與裝飾模式擴展JavaScript表單驗證功能,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

簡單的表單驗證

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>

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

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

之后再用設計模式豐滿

// validata.js
var 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

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

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

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

問題分析

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

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;
};

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

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

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

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

在這個地方我犯了一個小錯誤,導致我斷點調試了好長時間 __冏rz

Validator.prototype.start = function(){ //開始驗證表單
 for(var i = 0, vldFn; vldFn = this.rules[i++];){
 var warnMsg = vldFn();
 if(warnMsg){
  warn.textContent = warnMsg;
  return false;
 }
 }
}

改正前的錯誤代碼是這樣的

Validator.prototype.start = function(){ //開始驗證表單
 for(var i = 0, vldFn; vldFn = this.rules[i++];){
 var warnMsg = vldFn();
 if(warnMsg)
  warn.textContent = warnMsg;
  return false;
 }
}

沒錯,只是因為少加了那層大括號

可能是之前只有一行,后來添加return false的時候忘添加了

這里我只是為了簡潔才不寫大括號的

我們平時千萬不要這么寫代碼,簡直挖坑給自己跳

submitMsg = submitMsg.before(vld.start.bind(vld));

添加裝飾者這個地方也要注意

如果不寫bind就會發生this劫持,同樣會報錯

感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何使用策略模式與裝飾模式擴展JavaScript表單驗證功能”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阜阳市| 正定县| 邯郸市| 雷州市| 万全县| 依安县| 翼城县| 大宁县| 两当县| 吴堡县| 泸西县| 长顺县| 灵宝市| 孟连| 仪陇县| 长泰县| 五原县| 华宁县| 吉安市| 日喀则市| 婺源县| 永昌县| 新津县| 太原市| 泰来县| 吉安县| 沂源县| 习水县| 紫阳县| 陕西省| 噶尔县| 镇远县| 分宜县| 古丈县| 玉环县| 沛县| 集贤县| 昭苏县| 五峰| 仁寿县| 霍邱县|