基于微信小程序 + colorUI 做的form表单封装——picker

系列篇

基于微信小程序 + colorUI 做的form表单封装——input



前言

上周发了基于微信小程序 + colorUI 做的form表单封装——input之后,喜提三个评论 + 一个码云star,本想尽快整理出其他表单格式,但是年后公司项目开了不少,以至于一直拖到今天,给各位期待更新的小伙伴们(划掉、并没有这样的小伙伴)抱拳了,让你们久等了。

本篇为大家带来的是本系列的第二篇 ——picker(选择器)。表单格式的更新顺序,是按照本公司项目使用表单组件的频率高低更新的,大家更需要怎样的表单组件,请在评论区告诉我,我会提前更新。

由于本插件集成了一部分的业务代码,所以可配置项会少一点,对于与本插件业务符合度高的项目,用着会很方便;但是业务符合度低的,体验肯定会差很多。这个时候,欢迎大家去修改源码,使之符合自己的业务需求,同时我也会尽力将这些组件完善,将代码写的优美一些,让大家可以少走弯路,让我们一起学习、一起进步。

本系列的目的主要是记录学习+交流,非技术科普,大家有什么问题欢迎指出。

求赞求评论求star


一、先看效果

1.picker目前支持的动态配置

/**
     * 当且仅当 type === 'picker' 显示该组件
     * 
     * 参数说明
     * 公共参数:
     *      topLine            默认没有上划线,可加
     *      clearBottomLine    默认有下划线,可删
     *      label              输入框标题(最大长度为6,溢出隐藏)
     *      requied            是否必填(显示红星)
     *      submitName         向后台约定的数据提交字段名,如:姓名 —— name; 性别 —— sex; 年龄 —— age
     *      disabled           是否禁用
     *      value              选择的值
     *      placeholder + noPlaceholder        默认为“‘请选择’ + 输入框标题(label)” 通过placeholder可自定义
     *                                         也可通过noPlaceholder 来清除默认placeholder
     * 
     * 特定参数说明:
     * 当mode === 'selector'时, 选择器为单列选择器
     *      range              范围,目前支持俩种数据类型:
     *                           第一种:['中国', '美国', '日本']
     *                           第二种:[{ id: 0, name: '中国' }, { id: 1, name: '美国' }, { id: 2, name: '日本' }]
     *      rangeKey           当使用第二种jion类型时,需指定展示的字段名称,如该例子就需要指定rangeKey = 'name'
     *                         第一种类型就不要写这个参数了,切记切记
     *      dictField          如range是由接口动态获取的,那么在此配置参数,onLoad时会统一查询数据字典(详细代码已封装)
     * 
     * 当mode === 'time'时,选择器为时间选择器
     *      start - end        有效时间范围的开始or结束 默认不限制
     * 
     * 当mode === 'date'时,选择器为日期选择器
     *      start - end        有效日期范围的开始or结束 默认不限制
     *      fields             选择器的粒度,默认为day(天),可改为year(年)、month(月) 
     * 
*/

2.配置代码

{ label: '静态-数组', submitName: 'picker1', type: 'picker', mode: 'selector', value: '', requied: true, range: ['是', '否']},
{ label: '静态json', submitName: 'picker2', type: 'picker', mode: 'selector', value: '', requied: true,
rangeKey: 'name', range: [
        { id: '01', name: '美国' },
        { id: '02', name: '中国' },
        { id: '03', name: '巴西' },
        { id: '04', name: '日本' }
      ]},
{ label: '动态json', submitName: 'picker3', type: 'picker', mode: 'selector', value: '', requied: true, dictField: 'choose', range: [], rangeKey: 'name'},
{ label: '时间选择', submitName: 'picker4', type: 'picker', mode: 'time', value: '', requied: true, start: '05:05', end: '07:10'},
{ label: '日期选择', submitName: 'picker5', type: 'picker', mode: 'date', value: '', requied: true, start: '2021-01-01', end: '2025-01-01', fields: ''}

3.效果展示 

  • 配置完成后,只需上述简单的代码,就可以得到下图红框的picker选择器
  • picker选择内容后,会自动将内容发送到配置数组的 “value” 字段中,自动做必填验证
  • 需要接口请求的数据字典,只需要简单配置,就可实现选择器的动态数据加载
  • 目前支持单列选择器(静态数据 + 动态数据)、时间选择器、日期选择器
  • 二级、三级联动的选择器会单独开一篇文章细讲


二、详细步骤

1.引入colorUI和aw

  • 如果你对这个小插件感兴趣,但是并没有去看第一篇,那我强烈建议先去看一下:基于微信小程序 + colorUI 做的form表单封装——input,本篇代码是在上篇代码的基础上增加的,看完第一篇,使用的会更愉快一些
  • 由于本组件的ui主要用的是 colorUI ,所以先将 colorUI 应用到项目中,方法很简单,colorUI 的github描述的也很详细,在这里就不多赘述了
  • 码云github项目中下载aw
    (1)将utils文件夹下的“WxValidate.js” 、 “formMethods.js”和api文件夹,放入自己项目的utils文件夹下(最好放在根路径utils文件夹下,路径不同则需要在aw_picker.js中修改路径;已经引了的小伙伴可以重新拉取下最新的)

    可能出现的bug1:如果你看到这样的报错

    那是因为在request.js中使用了async/await,小程序默认是不支持这个特性的,但是要修改也很简单,打开本地配置的“增强编译”就好


    (2)将components中的form文件夹拉到你的项目里(不需要根目录,放在components下就可以)

    可能出现的bug2:如果路径路径不相同的话,此时控制台会弹一个报错


    这个报错是这行代码引起的,可能是获取的地址有问题,修改引入的地址就好



    这行代码的作用是当数据为动态获取时,所调的数据字典api接口,在“getRange”方法里有使用

    1、目前picker调用动态数据,主流的解决方案是在onshow的时候调接口并放入picker的range里,但是这种方法在实际项目过程中,是存在风险的,如onshow的时候,由于网络或者服务器原因,并没有拿到数据字典,那这时候我们就需要二次获取;

    2、针对这个问题,博主首先想到的方法是onshow的时候不做任何处理,点击picker时发起请求,拿到数据后渲染视图,但是这个方法失败了,我在微信开放社区反馈该问题点击 picker 动态获取数据,视图为什么不刷新?得到的回答是微信原生的picker容器并不支持这样做,好在给我指了一条明路——picker-view是支持的,所以我将这部分的逻辑改成了:onshow的时候调接口拿数据,如果数据拿到了,那么使用picker容器;如果因为一些问题,没拿到数据,那么使用我自己封装的picker-view容器;

    3、所以就很清楚了,报错的那行代码是点击picker-view时,去后台拿数据字典的。我们公司获取数据字典的接口,只有后面的参数有变化,比如:“abc.com/getdictField?name=choose”、“abc.com/getdictField?name=sex”, 这俩分别是获取“是否”和“性别”的,那我们只需要把后面的字段放到dictField字段中,之后拼接接口,获取数据(这段说的比较细,看着字多,其实很简单)

    4、本组件里是这样获取字典的,大家可能还需要微调下“getRange”函数


    5、当然,如果你的项目里,数据字典都是前端写的,以上你都可以忽略,直接把引入api的那行报错代码注释掉就可以了
  • 最后去app.json中的“usingComponents”里注册该组件(当然,也可以不注册全局组件,哪个页面用,在哪个页面注册也是可以的)

2.使用

  • 新建一个页面form(上篇就开始跟的大兄弟就不需要了),这就是要使用该组件的页面
  • 在form.wxml中添加如下代码
    <!--pages/form/form.wxml-->
    <view wx:for="{{form}}" wx:key="index">
      <aw-input wx:if="{{item.type === 'input'}}" formItem='{{item}}' index='{{index}}'></aw-input>
      <aw-picker wx:if="{{item.type === 'picker'}}" formItem='{{item}}' index='{{index}}'></aw-picker>
    </view>
    
    <!-- 点击该按钮验证是否符合规范 -->
    <button style="margin: 200px auto" bindtap="submitForm">提交</button>
  • 在form.js中的data里的form数组里增加如下代码

    { label: '静态-数组', submitName: 'picker1', type: 'picker', mode: 'selector', value: '', requied: true, range: ['是', '否']},
    { label: '静态json', submitName: 'picker2', type: 'picker', mode: 'selector', value: '', requied: true,
    rangeKey: 'name', range: [
            { id: '01', name: '美国' },
            { id: '02', name: '中国' },
            { id: '03', name: '巴西' },
            { id: '04', name: '日本' }
          ]},
    { label: '动态json', submitName: 'picker3', type: 'picker', mode: 'selector', value: '', requied: true, dictField: 'choose', range: [], rangeKey: 'name'},
    { label: '时间选择', submitName: 'picker4', type: 'picker', mode: 'time', value: '', requied: true, start: '05:05', end: '07:10'},
    { label: '日期选择', submitName: 'picker5', type: 'picker', mode: 'date', value: '', requied: true, start: '2021-01-01', end: '2025-01-01', fields: ''}
  • ok,给自己鼓个掌,我们成功一半了

  • 现在第一、第二、第四、第五个选择器已经可以正常工作了,选择数据后也会同步到form.js里data.form中
  • 第二条“动态数据”的选择器点击之后,我们看到选择列表是空的,那是因为我们给第二条增加了一个参数“dictField: 'choose'”,因为增加“dictField”字段,我们的组件就会认为它的range是需要动态获取的,所以接下来我们把批量获取数据字典的方法引进来

3.动态获取数据字典

想实现批量获取数据字典,我们只需要在onLoad函数中调用一个事先封装好的getFormDict函数

不需要动态获取数据字典的可跳过这段

  • 还记得我们前面在picker.js中引入的formMethods.js嘛?我们在form.js中同样引入formMethods.js。
    在这里引入的目的是要在onshow的时候统一批量获取数据字典;picker.js引入是防止onshow的时候有一些接口没有拿到数据,所以在点击picker-view组件的时候再次获取
  • // picker 批量获取动态数据
    const getFormDict = function(form, context) {
      form.forEach((item, index) => {
        if (item.type === 'picker' && item.dictField && item.dictField !== '') {
          /**
           * dictionary.getdictField 是封装好的获取数据字典的请求方法,大家可以使用自己的,也可以用我在request中封装好的
           * 目的是根据“dictField”值,取后台获取数据字典,并放入range中,就算成功
           * */ 
          dictionary.getdictField({name: item.dictField}).then(res => {
            if (res.code === 200) {  // onshow 获取动态字典请求成功、展示picker单选框
              let list = res.data;
              context.setData({ ['form['+ index +'].range']: list });
            } else {  // onshow 获取动态字典请求失败、展示自定义picker-view单选框,picker-view可以在点击的时候获取数据
              context.setData({ ['form['+ index +'].showPickerView']: true });
            }
          }).catch(err => { // onshow 获取动态字典请求失败、展示自定义picker-view单选框,picker-view可以在点击的时候获取数据
            console.log(err); 
            context.setData({ ['form['+ index +'].showPickerView']: true });
          })
        }
      })
    };

    以formMethods中的getFormDict为例(picker.js中的getRange函数类似,只是一个是批量发起请求,一个是单独发请求)
    代码逻辑超简单
    (1)遍历form,过滤需要发起数据字典的json;
    (2)拼接url,发起请求;
             ①请求成功,将数据字典塞入json的range中,数据覆盖,结束
             ②请求失败,将 “showPickerView”赋值为true,picker容器改为picker-view容器(俩个容器样式一样,不必担心视图有变化),到了这一步,picker.js中的getRange方法就能用上了,点击picker-view,可以重新发起请求,并渲染到视图中

  • 将picker.js的getRange方法与formMethods.js的getFormDict方法修改完后,第三个“动态数据”的选择器也应该成功了,现在只差最后一步,数据提交前的校验

4.数据校验

这个就更简单了,去form.js中复制submitForm函数,放到自己的form.js中就可以了

/**

     * 格式为:['中国', '美国'] 等数组类型的,value值为数组里的item

     * 格式为:[{name: '中国', id: '01'}, {name: '美国', id: '02'}]等json数组的,value值为json里的id

     * 也可以在submitForm函数中修改要放入value的参数

 */


总结

前面的步骤问题不大,主要是动态数据接口封装那,我可能夹带了自己的一些编程思想,以至于很局限,大家可能会看着不是很舒服,当然我只是提供一个思路,大家完全可以根据自己的编码风格封装一套适合自己的插件,重在交流嘛。

好的,到这里就picker的第一篇就正式结束了,二三级联动会在之后的篇幅中放出,大家觉得有用的话,请给我star鼓励一下。

有什么问题欢迎大家指出昂,再次感谢大家!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值