微信小程序之表单校验,微信小程序金山表单

来源:未知 浏览 209次 时间 2021-06-10 10:24

小程序SDK版本 1.4

表单校验之难

微信小程序之表单校验

表单组件在数量上达到11个居各类组件之首。当然幸运的是关键词居各类组件之首。当然幸运的是并不是所有的都需要校验。
而这些组件操作方式多样可分为滑动、(多行)输入、点击、点击+滑动。
即使是同一个组件因为业务场景不同就会有不同的校验规则。
更麻烦的是这些组件之间经常还会联动或者关联校验。

但是作为一个非简单静态页面有着较多用户交互的小程序表单校验又是一个非常常用的功能:登录、注册、新增、编辑…

总而言之:表单组件的多样性 X 校验规则的多样性 = 复杂的公共业务

微信小程序之表单校验

尝试组件化

如果你关注近年前端发展趋势一定会想到“组件化”来实现:

把每个表单组件的视图、样式、校验逻辑封装成单独的业务组件然后直接调用。

可事情似乎没这么简单。

如果考虑把n个原生组件抽象出来配上n个校验规则再乘以组件之间的关系n(的全排列)复杂度至少达到n³。

而且每个组件的校验失败或成功都要通知父组件以便显示错误信息或者进行下一步操作。

这样不但没有解决问题反而使得这些公用的表单组件过于复杂耦合混乱。

尝试非组件化

既然原先的思路行不通搜索引擎耦合混乱。

尝试非组件化

既然原先的思路行不通再来回到出发点看看我们最核心的需要被抽象出来的是什么。

无非是两样东西:视图层的元素样式和逻辑层的校验规则。

上面说到封装原生表单组件会极大的增加复杂度索性放弃它复杂度瞬间可以下降到n²。

但同时我们又要保持样式统一也就是我们常说的风格一致。

比如输入框该多高错误提示怎么显示字体大小颜色…之类的。

这个好办我们把样式类写入一个公共样式文件form.wxss然后需要的时候引入甚至可以全局引入。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

 

// form.wxss

.form {

 display: block;

 font-size: 28rpx;

 position: relative;

}

.form-line {

 background-color: #fff;

 border-bottom: 1px solid #e5e5e5;

 font-size: 34rpx;

 height: 96rpx;

 line-height: 96rpx;

 display: flex;

 padding: 0 31rpx;

}

.form-title {

 

 background-color: #efefef;

 color: #838383;

 font-size: 28rpx;

 padding: 31rpx;

 min-height: 90rpx;

}

...

 

我们使用的时候只需要在对应的元素上添加相应的样式即可。比如:

?

1

2

3

4

5

6

7

8

9

10

11

 

// xxx.wxml

<form class="form">

 <view class="form-title">请输入手机号</view>

 <view class="form-line">

  <label class="label">手机</label>

  <view class="form-control">

   <input class="f-1 va-m input" />

  </view>

 </view>

 ...

</form>

 

那么接下来我们只剩下校验规则和组件关联关系之间这两个难题了。

校验规则理想的状态是可扩展和可配置。

可扩展。随着业务的增长在不修改已有规则情况可以新增校验规则。

可配置。可单独为每个表单组件配置不同的单个或多个校验规则。

如何做到可定义?用统一的形式即可。比如:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

 

/*

统一的格式:

[规则名]: {

 rule: [校验方式]

 msg: [错误信息]

}

*/

const validators = {

 // 简单的校验用正则

 required: {

  rule: /.+/,

  msg: '必填项不能为空'

 },

 // 复杂的校验用函数

 same: {

  rule (val='', sVal='') {

   return val===this.data[sVal]

  },

  msg: '密码不一致'

 }

 ...

}

 

如何做到可配置?配置上支持类似数组的形式然后用统一的函数依次读取这些校验规则逐个校验。

配置的规则肯定是在原生表单组件上至于组件的值也只能通过事件对象获取。

如果直接绑定事件进行校验会阻碍父页面获取值搜索引擎至于组件的值也只能通过事件对象获取。

如果直接绑定事件进行校验会阻碍父页面获取值所以最好由父页面绑定事件传值并且传入事件对象和执行环境进行处理:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

 

/*

校验函数部分代码

e 事件对象

context 页面对象函数执行的上下文环境

*/

let validate = (e, context) => {

 // 从事件对象中获取组件的值

 let value = (e.detail.value || '').trim()

 // 从事件中获取校验规则名称

 let validator = e.currentTarget.dataset.validator ? e.currentTarget.dataset.validator .split(',') : []

 // 遍历规则进行校验

 for (let i = 0; i < validator.length; i++) {

  let ruleName = validator[i].split('=')[0]

  let ruleValue = validator[i].split('=')[1]

  let rule = validators[ruleName].rule || /.*/

  if ('function' === typeof rule) {

   rule.call(context, value, ruleValue) ? '' : validators[ruleName].msg

  } else {

   rule.test(value) ? '' : validators[ruleName].msg

  }

 }

 ...

}

 


调用起来也非常简单按照固定的格式加上对应的样式配置校验规则然后调用校验函数。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

 

// 部分代码示例

// page.wxml

<form>

 <!-- 一个表单组件 -->

 <view class="form-line">

  <label class="label">授权手机</label>

  <view class="form-control">

标签: 校验ltgt组件