Validator 验证器

随着Store在项目中使用范围增加,我们发现原有Model的设计使用起来还差了一点东西,那就是输入验证。

一般的工作流程是将验证放在view或ViewModel层,之后再赋值给Model。从功能实现上来说,这没有什么问题; 但我们从工程角度思考之后,觉得验证就应该放在Model,即使是在前端,也应该放在Model。

在Model验证实现了验证功能随着Model一起,变得可复用与可维护。 视图层只管往Model层写入,如果Model层验证失败,则返回错误信息,视图层收到信息后进行处理。

使用Validator定义Model,在前端,可以一次定义,两处使用:

如果你的服务器由nodejs书写,你可以再增加两处使用:

所以,Store推荐使用Validator代替原有的Model, 或者在后面的版本,会删除原有Model,使用Validator重新实现Model。

定义

Validator使用es7装饰器特性定义,所以你需要搭建es7转es3、es5或es6的编译环境。

下面是一个简单的示例:

import {Validator, Validates} from "sugo-store"
const {DateType, DateTypes, Required, Pattern, Range} = Validates

interface UserModel {
  id: string
  name?: string
}

class User extends Validator<UserModel> {
  @DateType(DataTypes.PRIM_S)
  @Required()
  id: string = null

  @Pattern(/[a-zA-Z]{2,32}/, "name只能为字母,长度为2~32位")
  @DateType(DataTypes.PRIM_S)
  name: string = null
}

const user = new User()
user.validOne("name", "a")  // name只能为字母,长度为2~32位
user.validOne("name", "aa") // null

继承

Validator中验证器可以被继承

interface VipUserModel extends UserModel {
  level: number
}
class VipUser extends User {
  @Range(0, 10)
  @Required()
  level: number = null
}

// 向上转型为Validator
const vipUser: Validator<VipUser> = new VipUser()
user.validOne("name", "a")  // name只能为字母,长度为2~32位
user.valid({level: 11})     // {level: Must be of type number that greater than 0 less than 10}

在Store中使用

Model类似,使用一个描述对象定义Validator,使用storeValidatorCreator将描述对象与Store关联。

描述对象属性如下:

interface UserState extends UserModel {
  message?: any
}

const store = new Store<{ User: UserState }>()
storeValidatorCreator({
  namespace: 'User',
  model: new User(),
  scheduler(action: Action, model: User, done: NextCallback<any>) {
    const { type, payload } = action
    switch (type) {
      case "upgrade":
        model.set(payload)
        done()
        break
      default:
        done()
    }
  },
  map(model: User) {
    return {
      name: model.name,
      message: model.getValid()
    }
  }
}, store)

store.subscribe(state => {
  console.log(state.User.name)     // A
  console.log(state.User.message)  // null
})
store.dispatch({ type: Action.upgrade, payload: { name: "A" } })

Validator 类接口说明

目前可用验证器列表