文章首发于 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 设计模式》
  1. 许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为
  2. 可作用于类或对象中的属性和方法
  3. 初始化时从上至下运行,执行时从内向外

代码来源: 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 校验对象有这些优点

  1. 代码更加直观,优雅,便于后续维护
  2. 支持异步校验:传递的校验函数返回 Promise 即可实现
  3. 按顺序校验:根据 decorator 执行的先后顺序

安装

npm install dvalidator --save
npm install @babel/plugin-proposal-decorators --save-dev

使用

配置 babel

plugins: [  [    '@babel/plugin-proposal-decorators',    {      legacy: true    }  ]]

原理

  1. 为对象增加 __rules 属性,并不可枚举,配置,写
  2. rules的属性与obj属性一一对应
  3. 每申明一个Decorator,其实都是更新 __rules 属性
  4. 调用 $validate 时,会根据 rules 对整个对象进行校验,返回 Promise,校验失败会返回所有失败信息

参考

  • http://es6.ruanyifeng.com/#do...
  • https://github.com/yiminghe/a...