表单验证

2018-11-30 06:41:33

验证是什么

在前后端各自为政的开发模式下,前端和后端需要单独实现各自的Form表单验证逻辑。Cabloy充分发挥全栈开发的优势,只需定义好JSON Schema配置信息,就可以同时支持前端与后端的Form表单验证逻辑。同时,还具备数据清洗特性,根据JSON Schema配置信息自动把表单字段转换成后端所需的数据类型

Cabloy的验证机制底层采用ajv,建议您对ajv有初步的了解

定义验证信息

以模块a-authsimplesignin验证逻辑为例:

1. schemas.js

配置todoJSON Schema,定义两个属性:authpasswordrememberMe

JSON Schema中的属性定义主要有两个用途:

  1. 在前端可以自动渲染Form表单
  2. 在后端验证Form表单数据,并清洗Form表单数据

a-authsimple/backend/src/config/validation/schemas.js

module.exports = app => {
  const schemas = {};
  schemas.signin = {
    type: 'object',
    properties: {
      auth: {
        type: 'string',
        ebType: 'text',
        ebTitle: 'Your mobile/email',
        notEmpty: true,
      },
      password: {
        type: 'string',
        ebType: 'text',
        ebTitle: 'Your password',
        ebSecure: true,
        notEmpty: true,
        minLength: 6,
      },
      rememberMe: {
        type: 'boolean',
        ebType: 'toggle',
        ebTitle: 'Remember me',
      },
    },
  };
  return schemas;
};
名称 说明
type 属性类型,如string/number/boolean
ebType 属性类型,用于标示前端渲染组件类型,如text/toggle/select
ebTitle 属性标题,用于前端渲染
notEmpty 标示此属性是否为空

2. meta.js

a-authsimple/backend/src/meta.js

module.exports = app => {
  const schemas = require('./config/validation/schemas.js')(app);
  return {
    validation: {
      validators: {
        signin: {
          schemas: 'signin',
        },
      },
      keywords: {},
      schemas: {
        signin: schemas.signin,
      },
    },
  };
};
名称 说明
validation.validators 声明模块所提供的validators清单
validation.keywords 声明模块所提供的keywords清单
validation.schemas 声明模块所提供的schemas清单

validatorschema的关系

  • 一个validator可以对应多个schema,但是一般场景只需提供一个schema

后端验证

模块a-validation提供了两个验证中间件:validatevalidation

1. validate

中间件validate根据路由配置的中间件参数,自动进行Form表单验证清洗逻辑

a-authsimple/backend/src/routes.js

{ method: 'post', path: 'auth/signup', controller: auth, middlewares: 'validate',
  meta: { 
    validate: { module: 'a-authsimple', validator: 'signup' } 
  },
},
名称 说明
middlewares: ‘validate’ 由于validate是局部中间件,需要显式声明
meta.validate 中间件参数
meta.validate.module 验证器所属模块,缺省为当前模块
meta.validate.validator 需要使用的验证器名称

2. validation

全局中间件validationctx.meta注入对象validation,便于直接通过代码进行验证

a-authsimple/backend/src/config/passport/auth.js

// validate
await ctx.meta.validation.validate({
  module: 'a-authsimple', validator: 'signin', data: body 
});
名称 说明
module 验证器所属模块,缺省为当前模块
validator 需要使用的验证器名称
data 需要验证的Form表单数据

前端渲染

模块a-components提供了一个全局vue组件eb-validate,主要有两个用途:

  1. 进行Form表单渲染
  2. 拦截后端返回的验证错误信息,并进行显示

1. 自定义渲染

eb-validate内部自定义Form组件布局,这样可以有更强的针对性和灵活性

a-authsimple/front/src/components/signin.vue

<template>
  ...
  <eb-validate ref="validate" :onPerform="onPerformValidate">
    <f7-list form no-hairlines-md>
      <f7-list-item>
        <f7-icon material="person_outline" slot="media"></f7-icon>
        <f7-label floating>{{$text('Your mobile/email')}}</f7-label>
        <eb-input type="text" :placeholder="$text('Your mobile/email')" clear-button v-model="auth" dataPath="auth"></eb-input>
      </f7-list-item>
    </f7-list>
  </eb-validate>
  <f7-list>
    <eb-list-button :onPerform="signIn">{{$text('Sign in')}}</eb-list-button>
  </f7-list>
  ...
</template>
<script>
export default {
  meta: {
    global: false,
  },
  data() {
    return {
      auth: null,
      password: null,
      rememberMe: false,
    };
  },
  methods: {
    onPerformValidate() {
      return this.$api.post('passport/a-authsimple/authsimple', {
        auth: this.auth,
        password: this.password,
        rememberMe: this.rememberMe,
      }).then(user => {
        this.$store.commit('auth/login', {
          loggedIn: true,
          user,
        });
        this.$meta.vueApp.reload();
      });
    },
    signIn() {
      return this.$refs.validate.perform();
    },
  },
};
  1. 所有Form表单字段都放到组件eb-validate
  2. 当点击按钮signIn时,执行validate.perform,以便触发onPerformValidate
  3. onPerformValidate中提交表单,如果有验证错误,会自动显示错误提示

2. 自动渲染

eb-validate根据validator提供的schema信息自动渲染Form表单

a-authsimple/front/src/pages/reset.vue

<template>
  <f7-page>
    <eb-navbar :title="$text('Reset password')" eb-back-link="Back"></eb-navbar>
    <f7-block>
      <eb-validate ref="validate" :auto="true" :data="data" :params="{module:'a-authsimple', validator: 'reset'}" :onPerform="onPerformValidate">
      </eb-validate>
      <eb-button v-if="!$config.test" :onPerform="onPerformOk">{{$text('OK')}}</eb-button>
    </f7-block>
  </f7-page>
</template>
<script>
export default {
  meta: {
    global: false,
  },
  data() {
    return {
      data: {
        passwordOld: null,
        passwordNew: null,
        passwordNewAgain: null,
      },
    };
  },
  methods: {
    onPerformValidate() {
      return this.$api.post('auth/reset', {
        data: this.data,
      }).then(() => {
        this.$f7Router.back();
      });
    },
    onPerformOk() {
      return this.$refs.validate.perform();
    },
  },
};
</script>
名称 说明
auto true:自动渲染 false:自定义渲染
data Form表单数据
params 自动布局参数
params.module 验证器所属模块,默认为当前模块
params.validator 验证器名称


评论: