常规来说 思路是这样的
let Form = document.querySelector('#Form')
Form.addEventListener('submit', function() {
if (Form.userName.value === '') {
alert('用户名不能为空!')
return false
}
if (Form.userName.length < 6) {
alert('用户名长度不能少于6位!')
return false
}
if (Form.passWord.value === '') {
alert('密码不能为空!')
return false
}
if (Form.passWord.value.length < 6) {
alert('密码长度不能少于6位!')
return false
}
if (Form.phoneNumber.value === '') {
alert('手机号码不能为空!')
return false
}
if (!/^1(3|5|7|8|9)[0-9]{9}$/.test(Form.phoneNumber.value)) {
alert('手机号码格式不正确!')
return false
}
if (Form.email.value === '') {
alert('邮箱地址不能为空!')
return false
}
if (!/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
$/.test(Form.email.value)) {
alert('邮箱地址格式不正确!')
return false
}
}, false)
☝
呃:这样的方法是不是很让人low[or]烦
这里说下方法,这也是我在以后项目中的——省时省事的方法
要实现的最终结果是:
// 获取表单form元素
let Form = document.querySelector('#Form')
// 创建表单校验实例
let validator = new Validator();
// 编写校验配置
validator.add(Form.userName, 'isNonEmpty', '用户名不能为空')
validator.add(Form.userName, 'minLength:6', '用户名长度不能小于6')
// 开始校验,并接收错误信息
let errorMsg = validator.start()
// 如果有错误信息输出,说明校验未通过
if(errorMsg){
alert(errorMsg)
return false//阻止表单提交
}
策略模式
注意,注意,注意 重要的事说三遍
策略模式其实就是解决事情的方法,比如说我们要去旅行:
- 可以乘坐:灰机,火车,地铁, 汽车,组团坐大巴,走路………..
我们今天要讲的策略模式也就是这个意思,它的核心思想是,将做什么和谁去做相分离。所以,一个完整的策略模式要有两个类,一个是策略类,一个是环境类(主要类),环境类接收请求,但不处理请求,它会把请求委托给策略类,让策略类去处理,而策略类的扩展是很容易的,这样,使得我们的代码易于扩展。
策略模式的组成
- 抽象策略角色:策略类,通常由一个接口或者抽象类实现。
- 具体策略角色:包装了相关的算法和行为。
- 环境角色:持有一个策略类的引用,最终给客户端用的。
编写策略类
/*策略对象*/
const strategies = {
isNonEmpty(value, errorMsg) {
return value === '' ?
errorMsg : void 0
},
minLength(value, length, errorMsg) {
return value.length < length ?
errorMsg : void 0
},
isMoblie(value, errorMsg) {
return !/^1(3|5|7|8|9)[0-9]{9}$/.test(value) ?
errorMsg : void 0
},
isEmail(value, errorMsg) {
return !/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value) ?
errorMsg : void 0
}
}
编写Validator类
/*Validator类*/
class Validator {
constructor() {
this.cache = [] //保存校验规则
}
add(dom, rules) {
for (let rule of rules) {
let strategyAry = rule.strategy.split(':') //例如['minLength',6]
let errorMsg = rule.errorMsg //'用户名不能为空'
this.cache.push(() => {
let strategy = strategyAry.shift() //用户挑选的strategy
strategyAry.unshift(dom.value) //把input的value添加进参数列表
strategyAry.push(errorMsg) //把errorMsg添加进参数列表,[dom.value,6,errorMsg]
return strategies[strategy].apply(dom, strategyAry)
})
}
}
start() {
for (let validatorFunc of this.cache) {
let errorMsg = validatorFunc() //开始校验,并取得校验后的返回信息
if (errorMsg) { //如果有确切返回值,说明校验没有通过
return errorMsg
}
}
}
}
客户端调用代码
/*客户端调用代码*/
let Form = document.querySelector('#Form')
const validatorFunc = () => {
let validator = new Validator()
validator.add(Form.userName, [{
strategy: 'isNonEmpty',
errorMsg: '用户名不能为空!'
}, {
strategy: 'minLength:6',
errorMsg: '用户名长度不能小于6位!'
}])
validator.add(Form.passWord, [{
strategy: 'isNonEmpty',
errorMsg: '密码不能为空!'
}, {
strategy: 'minLength:',
errorMsg: '密码长度不能小于6位!'
}])
validator.add(Form.phoneNumber, [{
strategy: 'isNonEmpty',
errorMsg: '手机号码不能为空!'
}, {
strategy: 'isMoblie',
errorMsg: '手机号码格式不正确!'
}])
validator.add(Form.email, [{
strategy: 'isNonEmpty',
errorMsg: '邮箱地址不能为空!'
}, {
strategy: 'isEmail',
errorMsg: '邮箱地址格式不正确!'
}])
let errorMsg = validator.start()
return errorMsg
}
Form.addEventListener('submit', function() {
let errorMsg = validatorFunc()
if (errorMsg) {
alert(errorMsg)
return false
}
}, false)
在修改某个校验规则的时候,只需要编写或者改写少量的代码。比如我们想要将用户名输入框的校验规则改成用户名不能少于4个字符。可以看到,这时候的修改是毫不费力的。代码如下:
validator.add(registerForm.userName, [{
strategy: 'isNonEmpty',
errorMsg: '用户名不能为空!'
}, {
strategy: 'minLength:4',
errorMsg: '用户名长度不能小于4位!'
}])
下面ES6的Proxy对象来实现
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
利用Proxy重构表单验证
利用proxy拦截不符合要求的数据
function validator(target, validator, errorMsg) {
return new Proxy(target, {
_validator: validator,
set(target, key, value, proxy) {
let errMsg = errorMsg
if (value == '') {
alert(`${errMsg[key]}不能为空!`)
return target[key] = false
}
let va = this._validator[key]
if (!!va(value)) {
return Reflect.set(target, key, value, proxy)
} else {
alert(`${errMsg[key]}格式不正确`)
return target[key] = false
}
}
})
}
负责校验的逻辑代码
const validators = {
name(value) {
return value.length > 6
},
passwd(value) {
return value.length > 6
},
moblie(value) {
return /^1(3|5|7|8|9)[0-9]{9}$/.test(value)
},
email(value) {
return /^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value)
}
}
客户端调用代码
const errorMsg = { name: '用户名', passwd: '密码', moblie: '手机号码', email: '邮箱地址' }
const vali = validator({}, validators, errorMsg)
let Form = document.querySelector('#Form')
Form.addEventListener('submit', function() {
let validatorNext = function*() {
yield vali.name = Form.userName.value
yield vali.passwd = Form.passWord.value
yield vali.moblie = Form.phoneNumber.value
yield vali.email = Form.email.value
}
let validator = validatorNext()
validator.next();
!vali.name || validator.next(); //上一步的校验通过才执行下一步
!vali.passwd || validator.next();
!vali.moblie || validator.next();
}, false)
es6语法记得 babel