taro react 自定义表单提交组件InputItem

项目中有一个表单提交的需求,表单内容样式较多,如果每个都写在同一个页面,那页面内容将会特别多 于是考虑到可拓展性 于是动手造轮子

根据相识度,将InputItem分成对应的几种类型 通过传参的方式显示不用的类型
InputItem组件中主要参数定义:
type类型 取值范围:input | text | radio | number | select 几种类型
input:类型为带输入框的样式 默认类型
text:类型为值类型 显示在最右边显示一个不可编辑的text
radio:radio类型 单选
number:包含inputNumber的样式
select:选项类型可以点击弹窗选择选项卡
title/subTitle:为显示在最做边的标题
placeholder:没值时input/select类型默认显示文案提示 请输入/请选择
min:inputNumber最小值
max:inputNumber最大值
maxlength:input类型可输入的最大长度
pickerItems:select类型需要的值列表 跟rangeKey保持绑定 [{value:'北京'},{value:'天津'}]
rangeKey:select类型列表对象中值绑定的属性默认为value 跟pickerItems息息相关
separator:select如果是多级选项卡选到的结果通过separator分隔 eg: 湖北省-武汉市-洪山区
radios:radio类型选项列表 [{ value: '1', name: '是' },{ value: '0', name: '否' }]
mode:select类型用到了Picker顺带这就把picker的几种类型也加入进来了 对应的取值范围 selector | multiSelector | date | time | region
selector单列滚轴 选完后返回value值
multiSelector多列滚轴 选完后返回vlaues值通过separator分隔的value 和 选中的对象列表datas
dater日期滚轴 点击返回选中的日期
time时间滚轴 点击返回选中的时间
region省市区滚轴 点击返回vlaues值通过separator分隔的value 和 选中的对象列表data

对应代码分析
1.input 输入监听和返回

/// 当类型为input
type === "input" ? (
              <Input
                className="input"
                placeholder={placeholder}
                type={inputType}
                maxlength={maxlength}
                disabled={editable === false}
                value={value}
                onInput={this.onInputValueChange.bind(this)}
              >
              </Input>
            )

  /// Input输入变化回调  通知引用方通过onValueChange保存键盘输入变化
  onInputValueChange = (e) => {
    const { value } = e.detail
    if (this.props.onValueChange) {
      this.props.onValueChange(value)
    }
  }
使用:
          <InputItem
            title="行驶里程数"
            placeholder="必填"
            inputType="number"
            maxlength={7}
            value={form.mileage}
            type="input"
            onValueChange={(val) => {
              form.mileage = val
              this.setState({
                form
              })
            }}
          ></InputItem>

2.text 直接显示无需回调

 type === "text" ? (
              <View className="text">{value}</View>
            )
使用:
<InputItem
  title="品牌"
  value={form.property_brand}
  type="text"
></InputItem>

3.radio 通过radios动态创建多个radio并通过onRadioChange接收用户的操作变化

 type === "radio" ? (
              <View className="radio">
                <RadioGroup onChange={this.onRadioChange.bind(this)}>
                  {
                    radios.map(item => {
                      return (
                        <Radio key={item.name} className="radio-item" value={item.value} checked={item.value == value} color="#E7242E" disabled={editable === false}>
                          {item.name}
                        </Radio>
                      )
                    })
                  }
                </RadioGroup>
              </View>
            ) 

  /// radio状态变化
  onRadioChange = (e) => {
    const { value } = e.detail
    if (this.props.onValueChange) {
      this.props.onValueChange(value)
    }
  }
使用:
<InputItem
  title="是否运营车辆"
  value={form.is_operate}
  type="radio"
  radios={[
    { value: '1', name: '是' },
    { value: '0', name: '否' }
  ]}
  onValueChange={(val) => {
    form.is_operate = val
    this.setState({
      form
    })
  }}
></InputItem>

4.number 用到了taro-ui中的AtInputNumber

type === "number" && (
          <View className="inputNumber">
            <AtInputNumber
              type="number"
              value={value}
              disabledInput={disabledInput}
              max={max}
              min={min}
              step={step}
              editable={editable}
              onChange={this.onInputNumberChange.bind(this)}
            ></AtInputNumber>
          </View>
        )

  /// InputNumber数据变化回调
  onInputNumberChange = (value) => {
    if (this.props.onNumberChange) {
      this.props.onNumberChange(value)
    }
  }

使用:
<InputItem
  title="数量"
  placeholder="必填"
  value={form.registration_num}
  type="number"
  disabledInput={true}
  max={numers.length}
  onNumberChange={(val) => {
    form.registration_num = val
    form.production_dates = production_dates
      this.setState({
        form
      })
  }}
></InputItem>

5.select 通过传入mode的不同Picker显示不同的mode 包含单选 多选 日期 时间 省市区选择

 {type === "select" ? (
              <View className={`picker ${value ? "" : "placeholder"}`}>{
                mode === 'selector' ? <Picker mode='selector' range={pickerItems} rangeKey={rangeKey} onChange={this.onPickerItemChange.bind(this)}>
                  {value || placeholder}
                </Picker> :
                  mode === 'multiSelector' ? <Picker mode='multiSelector' range={pickerItems} rangeKey={rangeKey} onChange={this.onMutilPickerItemChange.bind(this)}>
                    {value || placeholder}
                  </Picker> :
                    mode === 'date' ? <Picker mode='date' onChange={this.onDatePickerItemChange.bind(this)}>
                      {value || placeholder}
                    </Picker> :
                      mode === 'time' ? <Picker mode='time' onChange={this.onTimePickerItemChange.bind(this)}>
                        {value || placeholder}
                      </Picker> :
                        mode === 'region' ? <Picker mode='region' level="city" value={region} range={pickerItems} onChange={this.onRegionPickerItemChange.bind(this)}>
                          {value || placeholder}
                        </Picker> : null
              }
              </View>
            )

/// 对应回调方法
  onPickerItemChange = (e) => {
    const { rangeKey } = this.props
    const data = this.props.pickerItems[e.detail.value]
    const value = data[rangeKey]
    if (this.props.onPickerChange) {
      this.props.onPickerChange(value, data)
    }
  }

  onMutilPickerItemChange = (e) => {
    const { rangeKey } = this.props
    const count = e.detail.value.length
    var value = ''
    var list = []
    var values = []
    for (let i = 0; i < count; i++) {
      const data = this.props.pickerItems[i][e.detail.value[i]]
      values.push(data[rangeKey])
      list.push(data)
    }
    value = values.join(this.props.separator)
    if (this.props.onPickerChange) {
      this.props.onPickerChange(value, list)
    }
  }

  onDatePickerItemChange = (e) => {
    const { value } = e.detail
    if (this.props.onPickerChange) {
      this.props.onPickerChange(value)
    }
  }

  onTimePickerItemChange = (e) => {
    const { value } = e.detail
    if (this.props.onPickerChange) {
      this.props.onPickerChange(value)
    }
  }

  onRegionPickerItemChange = (e) => {
    const { value, postcode, code } = e.detail
    if (this.props.onPickerChange) {
      this.props.onPickerChange(value, postcode, code)
    }
  }
使用:
<InputItem
  title="单选"
  placeholder="请选择"
  value={form.property_brand}
  type="select"
  rangeKey='value'
  pickerItems={brands}
  onPickerChange={(val, data) => {
    form.property_brand = val
    form.property_brand_id = data.id
    this.setState({
      form,
    })
  }}
></InputItem>

<InputItem
  title="多选"
  placeholder="请选择"
  value={form.property_specification}
  type="select"
  mode="multiSelector"
  separator="/"
  rangeKey='value'
  pickerItems={multiArray}
  onPickerChange={(val, datas) => {
    form.property_specification = val
    form.property_specification_id = datas[0].id
    form.property_fineness_ratio_id = datas[1].id
    form.property_thickness_id = datas[2].id
    this.setState({
      form,
    })
  }}
></InputItem>

<InputItem
  title="日期"
  placeholder="请选择"
  value={form.date}
  type="select"
  mode="date"
  onPickerChange={(val) => {
    form.date = val
    this.setState({
      form,
    })
  }}
></InputItem>

<InputItem
  title="时间"
  placeholder="请选择"
  value={form.time}
  type="select"
  mode="time"
  onPickerChange={(val) => {
    form.time = val
    this.setState({
      form,
    })
  }}
></InputItem>

<InputItem
  title="省市区"
  placeholder="请选择"
  value={form.region}
  type="select"
  mode="region"
  onPickerChange={(val) => {
    form.region = val
    this.setState({
      form,
    })
  }}
></InputItem>

源码下载地址:https://github.com/qqcc1388/taro-input-item

posted @ 2022-04-26 16:23  qqcc1388  阅读(1370)  评论(0)    收藏  举报