小程序的表单的组件化封装及使用

3,204 阅读2分钟

表单说明

重构了小程序的表单组价(基于miaoUI小程序),微信小程序搜索miaoui

  • 配置化表单
  • 丰富的API,简化出错,提示等操作
  • 配置化表单联动

引入表单组件
表单组件属于 miaoui的核心组件,参考GITHUB

配置化

少模板化,代码量集中的JS中,减少直接操作模板

配置

const config = {
  data: [
    {input...},
    {button onClick=responseClick...}
  ]
}

function responseClick(){
  form.append({input...})
}

模板

<ui-form dataSource={config} />

结构

单表单

一个完整的表单,除了表单本体,还有如出错信息,是否必选,表单标题等等属性需要一些辅助结构来帮助表达,如下图

上图只是一个简单的示意,应该还需要诸如password的小眼睛,下拉菜单的小箭头等等UI层面的辅助结构。诸如上图的这些辅助结构可以通过配置传入,有值时显示,无值时不显示,另外还需要配套api,按照需求调用它们

const input = {type: 'text', id: 'uniq-id', value: '你好', className: '...'}

组表单

多个复合表单或者单表单混合在一起构成,它是完整的表单的一个独立部分,多个组表单合并构成完整表单,如下图

const input = {
  title: '组表单',
  input: [
    {表单配置一},
    {表单配置二},
    {表单配置三}
  ]
}

完整表单

由多个组表单构成完整表单,如下图

const formConfig = {
  $$id: 'uniq-id'
  formClass: 'form-container-class',
  data: [
    {
      title: '表单组一',  // 可包含多个单表单 
      input: [
        表单-1,
        表单-2
        ...
      ]
    },
  ]
}

表单示例

queryUI表单由配置文件生成,表单属性构成大致如下图

wxml

<ui-form wx:if="{{formConfig}}" dataSource="{{formConfig}}" /> 

js

const Pager = require('../../components/aotoo/core/index')
const config = [
  {
    title: '文本框表单区域',
    desc: '说明信息',
    input: [
      {
        id: 'aaa', type: 'text', title: '文本', placeholder: '数字输入键盘', 
        error: '错误信息',
        desc: '说明信息'
        bindblur: 'onbindblur',
        bindinput: 'onbindinput',
        bindfocus: 'onbindfocus',
        bindconfirm: 'onbindconfirm',
        bindkeyboardheightchange: 'onbindkeyboardheightchange',
      },
    ]
  },

  {
    title: '数字表单区域',
    input: [
      {id: 'ccc', type: 'number', title: '整数型', placeholder: '数字输入键盘', bindblur: 'onBlur'},
      {id: 'ddd', type: 'idcard', title: '身份证', placeholder: '身份证输入键盘', bindblur: 'onBlur'},
      {id: 'eee', type: 'password', title: '密码串', maxlength: 30, placeholder: '隐藏的密码串', bindblur: 'onBlur'}
    ]
  },

  {
    title: 'TEXTAREA',
    input: [
      {id: 'aaa', type: 'textarea', title: '文本域', placeholder: '输入文字', bindblur: 'onBlur'},
    ]
  },
]

const mthSet = {
  onbindblur(e) {
    console.log('=====text', e.detail.value);
  },
  onbindinput(e) {
    console.log('=====text', e);
  },
  onbindfocus(e) {
    console.log('=====text', e);
  },
  onbindconfirm(e) {
    console.log('=====text', e);
  },
  onbindkeyboardheightchange(e) {
    console.log('=====text', e);
  },
}

Pager({
  data: {
    formConfig: {
      ?id: 'myForm',
      formStyle: 'width: 90vw;',
      data: config,
      methods: mthSet
    },
  }
})

slider表单

wxml

<ui-form wx:if="{{formConfig}}" dataSource="{{formConfig}}" />  

js

const Pager = require('../../components/aotoo/core/index')
const config = [
  {
    title: '事件绑定',
    input: [
      {
        id: 'test_slider',
        title: 'slider',
        type: 'slider',
        value: 50,
        bindchange: 'onSliderChange',
        bindchanging: 'onSliderChanging',
      }
    ]
  },
],

const mthSet = {
  onSliderChange(e){
    console.log('======= slider change', e);
  },
  onSliderChanging(e){
    console.log('======= slider changing', e);
  },
}

Pager({
  data: {
    formConfig: {
      ?id: 'myForm',
      formStyle: 'width: 90vw;',
      data: config,
      methods: mthSet
    },
  }
})

复选框/单选框及表单事件绑定

同步微信小程序官方原生方法

wxml

<ui-form wx:if="{{formConfig}}" dataSource="{{formConfig}}" />

js

const Pager = require('../../components/aotoo/core/index')
const config = [
  {
    title: '事件绑定',
    input: [
      {
        name: 'test_checkbox1',
        type: 'checkbox',
        title: '复选框',
        value: ['1', '3'],
        values: ['1', '2', '3'],
        titles: ['篮球', '足球', '羽毛球'],
        bindchange: 'onbindchange'
      }
    ]
  },
],

const mthSet = {
  onbindchange(e) {
    console.log('======= checkbox', e);
  },
}

Pager({
  data: {
    formConfig: {
      ?id: 'myForm',
      formStyle: 'width: 90vw;',
      data: config,
      methods: mthSet
    },
  }
})

评分表单事件绑定

原生组件不包含此类型表单

  • 支持默认赋值
  • 支持点击赋值
  • 支持拖动赋值

wxml

<ui-form wx:if="{{formConfig}}" dataSource="{{formConfig}}" />  

js

const Pager = require('../../components/aotoo/core/index')
const config = [
  {
    itemClass: 'input-rating-list',
    title: '评分表单',
    input: {
      id: 'ratingit',
      title: '服务态度',
      type: 'rating',
      value: 4,  // 默认值
      max: 7, // 最大星星数
      tap: 'ratingChecked',  // 响应点击/滑动事件回调
    }
  },
]

const mthSet = {
  ratingChecked(e, param) {
    console.log('======= rating', e);
  },
}

Pager({
  data: {
    formConfig: {
      ?id: 'myForm',
      formStyle: 'width: 90vw;',
      data: config,
      methods: mthSet
    },
  }
})

picker表单事件绑定

wxml

    <ui-form wx:if="{{formConfig}}" dataSource="{{formConfig}}" />  

js

    const Pager = require('../../components/aotoo/core/index')
    const config = [
      {
        title: '事件绑定',
        input: [
          {
            id: 'test_pickers2',
            type: 'picker',
            title: '标题',
            value: [0, 2],
            values: [
              [
                {title: '猫科', id: '100'},
                {title: '狗科', id: '101'},
              ],
              [
                {title: '老虎', id: '102'},
                {title: '狮子', id: '103'},
                {title: '豹子', id: '104'},
                {title: '野狗', id: '105'},
              ],
            ],
            bindchange: 'pickerChange',
            bindcolumnchange: 'columnChangeAction',
          },
        ]
      },
    ],

    const mthSet = {
      pickerChange(e) {
        console.log(e);
      },
      columnChangeAction(e){
        if (e.detail.column === 0) {
          if (e.detail.value === 0) {
            this.updateNextColumn([  // 更新下一列
              {title: '老虎', id: '102'},
              {title: '狮子', id: '103'},
              {title: '豹子', id: '104', select: true},
              {title: '野狗', id: '105'},
            ])
          }
          if ( e.detail.value === 1) {
            this.updateNextColumn([ // // 更新下一列
              {title: '老虎', id: '102'},
              {title: '狮子', id: '103', select: true},
            ])
          }
        }
      },
    }

    Pager({
      data: {
        formConfig: {
          ?id: 'myForm',
          formStyle: 'width: 90vw;',
          data: config,
          methods: mthSet
        },
      }
    })

this.updateNextColumn方法为更新下一列数据,输入数组

联动配置

使用注册,消费的模式来设置表单联动

const formConfig = {
  data: [
    // 被关注的表单
    {title: '表单一', input: [
      {type: 'picker', id: 'picker-id', mode: 'time', value: ''},
    ]},
    
    // 定义观察者表单  
    {title: '表单一', input: [
      {type: 'text', id: 'text-id', value: '默认值', union: {
        id: 'picker-id',  // 使该表单观察picker组件
        callback(param){  // picker表单change后触发此回调
          this.save({value: param.value})  // 联动设置表单本身的值
        }
      }},
    ]},
  ]
}

表单实例

获取实例后可通过实例的API方法操作表单

// $$id 属性用来获取表单实例的关键属性  
Pager.onReady = function(){  // 注意,Pager是miaoui对小程序Page的封装
  const formInst = this.getElementsById('form-id')  // form-id 为表单配置的$$id属性
}

getValue([id])

一次性获取所有表单的值
通过form的实例获取表单元素的值

获取指定表单

formInst.getValue('id')  // 指定表单id的value

获取所有表单值

formInst.getValue() 

setValue(id, value)

为某个指定id的表单赋值,或者为多个表单赋值

赋值指定表单

formInst.setValue('id', '....')  // 指定表单id的value

赋值多个指定表单

formInst.setValue({  // 指定表单id的value
  'input-id-1': '....',
  'input-id-2': '....'
})  

empty(id)

清空指定表单

formInst.empty('id')  // 清空指定表单value

清空所有表单

formInst.empty()  // 清空所有表单value

addWarn(id, message)

指定表单显示警告信息

formInst.addWarn('id', '警告信息')

removeWarn(id)

清空指定表单警告信息

formInst.removeWarn('id', '警告信息')

addClass(id, className)

指定表单增加样式类名

formInst.addClass('id', 'class-name')

removeClass(id, className)

清除指定表单样式类名

formInst.removeClass('id', 'class-name')

union(id, callback)

使外部组件能够联动表单

源码

GITHUB
/pages/form

下列小程序DEMO包含下拉菜单、通用型筛选列表、索引列表、markdown(包含表格)、评分组件、水果老虎机、折叠面板、双栏分类导航(左右)、刮刮卡、日历等组件