表单组件使用小练习——制作一套微信风格的动态表单
发布于 3 年前 作者 kxiao 3515 次浏览 来自 分享

表单组件使用小练习笔记——制作一套微信风格的动态表单

写在前面

使用git仓库的quick start进行快速体验一番:

WeuiDynamicForm (gitee.com)

一、 效果

一次网络维修的工单提交流程是这样的:

用户选择服务->小程序获取该服务所指定的表单设置数据->小程序展示表单->

用户按照格式进行填写->小程序根据表单设置进行数据校验->小程序提交表单

二、需求

  • 通过json或js数据对表单进行渲染
  • 表单组件可以输入和输出数据

三、思路

  • 传入一个组件数据对象list,通过wx:forwx:if去判断“组件类型、组件设置”;
  • 表单组件能够正常将值传递到表单待校验的数据中;

伪代码:

四、开干

1、通过表单设置对表单进行渲染

(一) 新建项目,通过NPM的方式引入同微信原生视觉体验一致的UI组件库weui

(1)通过useExtendedLib方式引入weui组件库

通过npm或useExtendedLib方式引入组件库 | 微信开放社区 (qq.com)

  • 顺便看看官方的组件展示,可以归纳为以下这些
  • 选择列表:选项会以列表的方式展示

  • 输入框包含标题:一种样式;

  • 输入框包含标题及按钮;

  • 日期输入框;

  • 图片选择框

(2)先放下一个大表单

(3) 再搭建一个单一表单组件的样子 ,通过wx:for进行遍历,

(二)将单个组件的设置传入对应的表单组件中

其实就是把每个元素的设置都传进去就好了,输入框同理

(三)将部分特殊的组件独立出一个组件

可以不分开,但考虑到代码的整洁,决定将一些复杂的组件独立出来

这里以图片选择组件为例

(1)图片选择器

创建一个新的组件,组件中引入weui的uploader,然后将官方文档的wxml js代码粘贴进来Uploader | 微信开放文档 (qq.com)

{
    "component": true,
    "usingComponents": {
        "mp-uploader": "weui-miniprogram/uploader/uploader"
    }
}

在大表单中引入自定义组件,包括两步,在json中配置usingComponents,然后放入组件的标签,传入单个表单组件的数据

再在自定义组件中,将部分官方放的静态数据替换成动态的

从官方文档中,我们可以看出这个图片上传组件的工作流程是这样的:

那我们的工作就简单了,我们只需要实现uploadFile里面的上传函数即可,最后在uploadSuccess方法里面将事件传递出去

  • 组件间通讯,仅传递事件

如图,我们需要在my-uploader.js里的uploadSuccess里面使用this.triggerEvent将事件传递上去,注意,这只是说明操作逻辑的图,不代表实际传递过程。

  • 操作过程

    • 在最外层的<my-uploader/>里绑定事件
    • my-uploader.js的图片上传成功回调里面使用this.triggerEvent()触发事件

(2)图形验证码组件

  • 我们需要实现验证码的生成,将组件输入框及验证码加密后的数据传递到表单页中

图像生成:使用云函数配合captchapng库生成base64编码的验证码图片字符串并返回;

验证码校验:将用户输入结果使用配置数据库的盐值进行解密

npm install --save captchapng

var captchapng = require('captchapng')
  var vcodeInt = parseInt(Math.random() * 9000 + 1000)
  var vcodeRaw = new captchapng(80, 30, vcodeInt)
  // width,height,numeric captcha
  vcodeRaw.color(0, 0, 0, 0) // First color: background (red, green, blue, alpha)
  vcodeRaw.color(80, 80, 80, 255) // Second color: paint (red, green, blue, alpha)
  var vcodeRaw64 = vcodeRaw.getBase64()
  var vcodeBase64 = new Buffer(vcodeRaw64, 'base64')

  //选择性进行MD5加盐
  //设置加密字符串
  var salt = ''
  //在原来的字符串的基础上加上一些特殊文本
  var vcodeEncrypt =  md5(salt + vcodeInt)
    return {
    openid: OPENID,
    vcodeImg: vcodeBase64.toString('base64', 0),
    vcodeEncrypt: vcodeEncrypt
  }

拿到图片的base64字符串后,在<image/>里进行回显

当然,图片的点击会再次召唤新的验证码

2、表单数据校验

Form | 微信开放文档 (qq.com)

从文档得知,表单数据校验需要设置“规则”和“需校验数据”,重点:了解“规则”和“数据”是如何联系的

(一)传入规则及数据

  • 规则设置及传入

将包含一整个表单规则的数组丢进去即可

  • 需校验的数据

将整个表单的数据传入即可

(二)将“规则”和“数据”联系起来

(1)阅读官方的规则,发现是这样连起来的

规则名称对应models对象的一个结点名称

        <mp-form id="form" rules="{{formConfig.rules}}" models="{{formData}}">
{
            name: 'ticketClass',
        rules: {required: true, message: '分类多少选一个吧'},
}

如上述规则,他的名字是ticketClass,那如果需要对他进行校验,那他在大的动态表单form里面需要是formData.ticketClass

(2)这样的目标就很明确了,我们需要对formData进行赋值,名称是这个字段的名称,值是输入值
  • 普通表单组件

官方demo里面,每个表单组件都有一个属性data-feild

在每次对组件进行事件监听时,在返回的事件对象中,我们可以在

event.currentTarget.dataset中找到数据名称

event.detail.value中找到数据值

然后,我们将“名称”和“值”放到formData上,使用this.setData({})方法进行赋值,其中,值的名称是动态的,采用一个小点,不是单引号!(因为在markdown的缘故,无法在这单独打这样一个点出来,自行体会一下,常规的87 104键键盘会在左上角数字1的左边,点${能返回值的函数或者值}点是ES6新增的字符串方法)

            const {
                field
            } = event.currentTarget.dataset
			this.setData({
                [`formData.${field}`]: event.detail.value
            })

五、小提问

  • 可否通过设置表单id的方式,一次性生成多张表单呢?
  • 如何使用<slot/>的方式优化渲染性能呢?
5 回复

写得很好,对练习前端开发很有帮助~~加油呀!(后面两个问题我也不会QAQ)

写的很详细,配图也很多,对表单组件的了解更深了,赞~

配套b站视频,终于传完了

好好好,收藏了

或许你尝试下定义 template 模板文件, 比你一大段 wx:if 要优雅得多

回到顶部