-
Notifications
You must be signed in to change notification settings - Fork 840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
探索两种优雅的表单验证——策略设计模式和ES6的Proxy代理模式 #19
Comments
受教 |
只要我还在学习和摸索,我就把自己学到的记录下来,分享给大家 |
策略模式没有留出口吧,所有条件检验成功后,再次点击提交this.cache会报错, |
什么错误,能看一下截图吗,确保在chrome浏览器下测试,我这边测试都没问题的。@BiYuqi |
实在抱歉,是我的问题,我没有用es6写。导致用普通for循环条件判断结束后出错,现在已经修正,向您学习 |
大神,还缺基友么。 |
原生JS看起来就是很舒服 |
火钳刘明 |
手脚了 |
学习了! (最后 Refs 放的居然不是豆瓣读书的链接...) |
赞,个人最近在看一本关于JavaScript设计模式的书,将设计模式结合在工作与实践中,对代码的整体结构和设计都有很大的帮助,有利于梳理逻辑和后续的维护工作。 |
我运行了原始的验证方法,就好多if 那个,但是发现在验证未通过情况下点击提交之后,依然会提交。后来加了preventDefault之后才阻止了提交。请问博主你那是这样的吗? |
好像是的啊,不过影响不大,知道思路就行 @Goldbeener |
最喜欢这种结合设计模式编写的代码了,看着就舒服,最近也在看js设计模式的书,获益良多 |
按照上面的代码 校验不通过控制台会报错 'set' on proxy: trap returned falsish for property 'passwd' |
es6结合设计模式简直太清晰强大了! |
这样最后提交的时候验证只需要实例化一次,要是每个表单元素都实时验证那不是要实例化多个? |
为什么后面还要用 generator函数,多余了 |
Proxy部分有点生硬的,同样思路不用Proxy感觉反而会更好 |
Proxy部分很强大很简洁~~~~谢谢 |
好文,逻辑看起来清晰明了! |
不错 |
严格模式下return false会报错 |
@TopGrd 请问看的哪一本呀 |
转载了,前端读者 公众号,让更多人学习学习 ^_^ |
JavaScript设计模式与开发实践我觉得腾讯大佬的这本不错,感觉这篇文章的作者应该也看过,因为举的例子差不多~ |
大兄弟,你第一个策略模式的例子, 至少放一下参考的出处吧 JavaScript设计模式与开发实践, 也算是对别人著作的尊重 |
策略模式那部分的例子很不错,但我想的是在某些情况下策略模式是否可以简化成一种hash map的形式,我们将算法定义在一个hashMap中,然后通过match的方式,调用这些方法,这样是否也能称之为策略模式? const matchMap = {
handleSomeThing: () => {
console.log('got control');
},
}
matchMap['handleSomeThing']() |
大哥....第一个html的提交按钮改成type ='submit'. |
大佬,策略模式的那个例子里的validator.add 和validator.start我可不可理解为使用了职责链模式?add方法相当于指定了职责链的链条顺序,start方法则是开始是执行链条? |
第一种验证方式中,isMoblie拼写错误,应该是isMobile |
真的很棒!!感觉最后一段用async await 改一下会更易读一点。 |
原文收录在我的 GitHub博客 (https://github.com/jawil/blog) ,喜欢的可以关注最新动态,大家一起多交流学习,共同进步,以学习者的身份写博客,记录点滴。
假设我们正在编写一个注册的页面,在点击注册按钮之前,有如下几条校验逻辑。
注:为简单起见,以下例子以传统的浏览器表单验证,
Ajax
异步请求不做探讨,浏览器端验证原理图:简要说明:
HTML代码:
JavaScript代码:
1、问题
这样编写代码,的确能够完成业务的需求,能够完成表单的验证,但是存在很多问题,比如:
所谓办法总比问题多,办法是有的,比如马上要讲解的使用 策略模式 使表单验证更优雅更完美,我相信很多人很抵触设计模式,一听设计模式就觉得很遥远,觉得自己在工作中很少用到设计模式,那么你就错了,特别是
JavaScript
这种灵活的语言,有的时候你已经在你的代码中使用了设计模式,只是你不知道而已。更多关于设计模式的东西,以后会陆续写博客描述,这里只希望大家抛弃设计模式神秘的感觉,通俗的讲,它无非就是完成一件事情通用的办法而已。2、思路
回到正题,假如我们不想使用过多的
if - else
语句,那么我们心中比较理想的代码编写方式是什么呢?我们能不能像编写配置一样的去做表单验证呢?再来一个”一键验证“的功能,是不是很爽?答案是肯定的,所以我们心中理想的编写代码的方式如下:怎么样?感受感受,是不是看上去优雅多了?好了,有了这些思路,我们就可以向目标迈进了,下一步就要了解了解什么事策略模式了。
3、策略模式
策略模式,单纯的看它的名字”策略“,指的是做事情的方法,比如我们想到某个地方旅游,你可以有几种策略供选择:
1、飞机,嗖嗖嗖直接就到了,节省时间。
2、火车,可以选择高铁出行,专为飞机恐惧症者提供。
3、徒步,不失为一个锻炼身体的选择。
4、other method……
在程序设计中,我们也经常遇到类似的情况,要实现一种方案有多种方案可以选择,比如,一个压缩文件的程序,即可选择zip算法,也可以选择gzip算法。
所以,做一件事你会有很多方法,也就是所谓的策略,而我们今天要讲的策略模式也就是这个意思,它的核心思想是,将做什么和谁去做相分离。所以,一个完整的策略模式要有两个类,一个是策略类,一个是环境类(主要类),环境类接收请求,但不处理请求,它会把请求委托给策略类,让策略类去处理,而策略类的扩展是很容易的,这样,使得我们的代码易于扩展。
在表单验证的例子中,各种验证的方法组成了策略类,比如:判断是否为空的方法(如:isNonEmpty),判断最小长度的方法(如:minLength),判断是否为手机号的方法(isMoblie)等等,他们组成了策略类,供给环境类去委托请求。下面,我们就来实战一下。
4、用策略模式重构表单校验
策略模式的组成
4.1具体策略角色——编写策略类
策略类很简单,它是由一组验证方法组成的对象,即策略对象,重构表单校验的代码,很显然第一步我们要把这些校验逻辑都封装成策略对象:
4.2抽象策略角色——编写Validator类
根据我们的思考,我们使用
add
方法添加验证配置,如下:add
方法接受三个参数,第一个参数是表单字段,第二个参数是策略对象中策略方法的名字,第三个参数是验证未通过的错误信息。然后使用
start
方法开始验证,若验证未通过,返回验证错误信息,如下:另外,再解释一下下面这句代码:
add
方法第一个参数我们说过了,是要验证的表单元素,第二个参数是一个字符串,使用 冒号(:) 分割,前面是策略方法名称,后面是传给这个方法的参数,第三个参数仍然是错误信息。但是这种参数配置还是有问题,我们的要求是多种校验规则,比如用户名既不能为空,又要满足用户名长度不小于6,并不是单一的,上面的为什么要写两次,这种看着就不舒服,这时候我就需要对配置参数做一点小小的改动,我们用数组来传递多个校验规则:
最后是Validator类的实现:
4.3环境角色——客户端调用代码
使用策略模式重构代码以后,我们仅仅通过‘配置’的方式就可以完成一个表单的校验,这些校验规则也可以复用在程序的任何地方,还能作为插件的形式,方便地被移植到其他项目中。
在修改某个校验规则的时候,只需要编写或者改写少量的代码。比如我们想要将用户名输入框的校验规则改成用户名不能少于4个字符。可以看到,这时候的修改是毫不费力的。代码如下:
4.4策略模式的优缺点
当然,策略模式也有一些缺点,但掌握了策略模式,这些缺点并不严重。
4.5策略模式的意义
策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系。
弱连接的特性使软件具有更强的可扩展性,易于维护;更重要的是,它大大提高了软件的可重用性。
关于ES6d的Proxy对象
策略模式固然可行,但是包装的有点多了,而且不便于书写,代码书写量增加了不少,也就是有一定门槛,那有没有更好的实现方式呢?我们能不能通过一层代理,在设置属性时候就去拦截它呢?这就是今天要讲到的ES6的Proxy对象。
1、概述
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
上面代码对一个空对象架设了一层拦截,重定义了属性的读取(
get
)和设置(set
)行为。这里暂时先不解释具体的语法,只看运行结果。对设置了拦截行为的对象obj
,去读写它的属性,就会得到下面的结果。上面代码说明,Proxy 实际上重载(overload)了点运算符,即用自己的定义覆盖了语言的原始定义。
ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
Proxy 对象的所有用法,都是上面这种形式,不同的只是
handler
参数的写法。其中,new Proxy()
表示生成一个Proxy
实例,target
参数表示所要拦截的目标对象,handler
参数也是一个对象,用来定制拦截行为。下面是另一个拦截读取属性行为的例子。
上面代码中,作为构造函数,
Proxy
接受两个参数。第一个参数是所要代理的目标对象(上例是一个空对象),即如果没有Proxy
的介入,操作原来要访问的就是这个对象;第二个参数是一个配置对象,对于每一个被代理的操作,需要提供一个对应的处理函数,该函数将拦截对应的操作。比如,上面代码中,配置对象有一个get
方法,用来拦截对目标对象属性的访问请求。get
方法的两个参数分别是目标对象和所要访问的属性。可以看到,由于拦截函数总是返回35
,所以访问任何属性都得到35
。注意,要使得
Proxy
起作用,必须针对Proxy
实例(上例是proxy
对象)进行操作,而不是针对目标对象(上例是空对象)进行操作。2、利用Proxy重构表单验证
利用proxy拦截不符合要求的数据
负责校验的逻辑代码
客户端调用代码
优点:条件和对象本身完全隔离开,后续代码的维护,代码整洁度,以及代码健壮性和复用性变得非常强。
缺点:兼容性不好,有babel怕啥,粗糙版,很多细节其实还可以优化,这里只提供一种思路。
参考文献
JavaScript设计模式与开发实践
ECMAScript 6 入门
策略模式在表单验证中的应用
The text was updated successfully, but these errors were encountered: