文章首发于 shuaizhang.top
Decorator 已经提案很久了,已经有过很大的改动。本文基于老的提案实现。
前言
有了 Decorator,我认为表单校验方式会有更多的玩法。所以基于 Decorator 实现了一个纯净的对象校验的库 dvalidator。
在无任何校验库的帮助下,我们可能会写出这样的代码
let form = { nickname: '', password: ''}function submit() { if (!checkNickName(form.nickname)) { alert('昵称格式不正确') return } if (!checkPassword(form.password)) { alert('密码格式不正确') return } remoteValid(form.nickname) .then(() => { // do next }) .catch(() => { alert('昵称已被注册') })}
使用 dvalidator 我们可以这样写
import dvalidator from 'dvalidator'let form = { @dvalidator(remoteValid)('昵称已被注册') @dvalidator(checkNickName)('昵称格式不正确') nickname: '', @dvalidator(checkPassword)('密码格式不正确') password: ''}function submit() { form .$validate() .then(() => { // do next }) .catch(error => alert(error[0].message))}
Decorator 基础
“装饰者模式:在不改变原对象的基础上,通过对其进行包装拓展(添加属性或者方法)使原有对象可以满足用户的更复杂需求。”
--《JavaScript 设计模式》
- 许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为
- 可作用于类或对象中的属性和方法
- 初始化时从上至下运行,执行时从内向外
代码来源: http://es6.ruanyifeng.com/#docs/decorator#%E6%96%B9%E6%B3%95%E7%9A%84%E4%BF%AE%E9%A5%B0
function dec(id){ console.log('evaluated', id); return (target, property, descriptor) => console.log('executed', id);}class Example { @dec(1) @dec(2) method(){}}// evaluated 1// evaluated 2// executed 2// executed 1
使用 dvalidator
使用 dvalidator 校验对象有这些优点
- 代码更加直观,优雅,便于后续维护
- 支持异步校验:传递的校验函数返回 Promise 即可实现
- 按顺序校验:根据 decorator 执行的先后顺序
安装
npm install dvalidator --save
npm install @babel/plugin-proposal-decorators --save-dev
使用
配置 babel
plugins: [ [ '@babel/plugin-proposal-decorators', { legacy: true } ]]
原理
- 为对象增加
__rules
属性,并不可枚举,配置,写 - rules的属性与obj属性一一对应
- 每申明一个Decorator,其实都是更新
__rules
属性 - 调用
$validate
时,会根据 rules 对整个对象进行校验,返回 Promise,校验失败会返回所有失败信息
参考
- http://es6.ruanyifeng.com/#do...
- https://github.com/yiminghe/a...