js 策略模式 实现表单验证
策略模式
简单点说就是:实现目标的方式有很多种,你可以根据自己身情况选一个方法来实现目标.
所以至少有2个对象 . 一个是策略类,一个是环境类(上下文). 然后自己就可以根据上下文选择不同的策略来执行方案.
策略模式的优点:
1. 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句
2. 策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的 策略类 中,使得它们易于切换,易于理解,易于扩展.
// html
<!DOCTYPE html> <head> <meta charset="utf8"> <title>策略模式实现表单验证</title> <link rel="stylesheet" type="text/css" href="style.css"> <script src="rule.js"></script> <script src="validator.js"></script> </head> <body> <form action="#" method="GET" id="form"> <div class="field"> <label>用户名</label> <input type="text" name="name"> </div> <div class="field"> <label>联系电话</label> <input type="text" name="mobile"> </div> <div class="field"> <label>邮箱</label> <input type="text" name="email"> </div> <button class="submit" type="submit">提交</button> </form> <script> let dom = document.getElementById("form"); let formValid = new FormValid(dom); formValid.add({ field: "name", rule: new RequiredRule(), errormsg: "字段必填" }) formValid.add({ field: "name", rule: new LengthRule(10), errormsg: "限定长度为10个字符" }) formValid.add({ field: "mobile", rule: new MobileRule(), errormsg: "手机号码错误" }) formValid.add({ field: "email", rule: new EmailRule(), errormsg: "邮箱格式错误" }) dom.onsubmit = function (event) { let result = formValid.isValid(); if (result !== true) { alert(result); return false; } alert("提交成功"); } </script> </body> </html>
// css
#form{ margin: 50px auto; width: 500px; } input { width: 350px; height: 24px; padding: 0 4px; float: left; } .field{ margin-top: 10px; overflow: hidden; } label { float: left; text-align: right; width: 100px; overflow: hidden; padding-right: 5px; } .submit{ margin-top: 20px; margin-left:104px; }
// 策略类
/** * 必填 */ class RequiredRule { /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @param {any} attach 附加参数 * @returns {string|bool} */ test(value, errormsg, attach) { return /^(:?\s*)$/.test(value) ? errormsg : true; } } /** * 范围 */ class RangeRule { /** * 构造函数 * @param {array} range */ constructor(range) { this.range = range; } /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @returns {string|bool} */ test(value, errormsg) { value = Number.parseFloat(value); if (this.range[0] <= value && this.range[1] > value) { return true; } return errormsg; } } /** * 有效数值验证 */ class NumberRule { /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @returns {string|bool} */ test(value, errormsg) { return /^(?:\d+)$/.test(value) || errormsg; } } /** * 邮箱验证 * 格式:登录名@主机名.域名 */ class EmailRule { constructor() { this.rule = new RegExp(/(?:\w+)@(?:\w+)\.(?:\w+)/); } /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @returns {string|bool} */ test(value, errormsg) { return this.rule.test(value) || errormsg; } } /** * 手机号验证 */ class MobileRule { constructor() { this.rule = new RegExp(/^1\d{10}$/); } /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @returns {string|bool} */ test(value, errormsg) { return this.rule.test(value) || errormsg; } } class LengthRule { constructor(maxlength) { this.maxlength = maxlength; } /** * 验证 * @param {string} value 值 * @param {string} errormsg 错误信息 * @returns {string|bool} */ test(value, errormsg) { return value.length > this.maxlength ? errormsg : true; } }
// 环境类
class FormValid { /** * 构造函数 * @param {HTMLFormElement} form 元素节点 */ constructor(form) { this.form = form; this.rules = []; } /** * 添加验证规则 * @param {object} option * @param {string} option.field 字段名 * @param {object} option.rule 规则 * @param {string} option.errormsg 错误信息 */ add({ field, rule, errormsg }) { if (typeof rule.test == "function" && this.form[field]) { this.rules.push(() => { return rule.test(this.form[field].value, errormsg); }); } } isValid() { let result = []; for (let i = 0; i < this.rules.length; i++) { let r = this.rules[i](); if (r !== true) result.push(r); } return result.length > 0 ? result : true; } }
源码:https://pan.baidu.com/s/17_oBg1dqmbxAdG_AW3sWgg
样本:http://js.zhuamimi.cn/%E8%A1%A8%E5%8D%95%E9%AA%8C%E8%AF%81/