React-Native开发从入门到实战项目总结React-Native 开发阵营React Native开发

React Native封装Form表单组件

2017-11-29  本文已影响492人  光强_上海

React Native封装Form表单组件

为什么我们在移动端开发中急需要一个完善的Form表单组件尼?做过移动端开发的小伙伴们应该都清楚,一个完整的App项目中避免不了要有登录注册功能,用户信息,密码等一系列需要新用户填写信息的页面,这些页面的UI如果都是按部就班的去绘制,其实是做了很多无用功,因为大部分UI都长的差不多,就是有些文案类的略微不同,既然这样,我们将这些长的差不多的UI抽离成组件,在需要用到的地方,直接调用封装好的组件,这样极大的降低了编写代码量,大大的提高开发者的效率

Form表单支持的可配置项

后续待添加的配置项

效果图

image

主要功能

后期完成登录注册、身份认证等表单信息页面的开发,我们只需要一个简单的配置文件即可搞定,不必每次相同的表单项都重新绘制一遍UI。对于哪些不常见的表单项,我们可以完全使用自定义UI来搞定,这样一来,我们在平时开发中的80%的表单需求都能轻松的搞定了

核心代码

renderFields(fields) {

    let fieldCount = fields.length ? fields.length : 0

    return fields.map((field, index) => {

      let isLastField = true
      if (fieldCount === index + 1 || fields[index + 1].title !== undefined) {
        isLastField = false
      }

      if (field.title !== undefined && field.show !== false) {
        return this.renderGroupForm(field)
      } else {
        let {show, type, label, subLabel, subTitle, ...other} = field
        let otherProps = {...other}
        Object.keys(otherProps).map((key, index) => {
          if (key.indexOf('on') === 0 || key === 'callback' || key === 'dataFunc' || key === 'view') {
            otherProps[key] = this.props[otherProps[key]]
          }
        })

        let isEditable = !this.props.readOnly && !this._isReadOnly(field.readOnly)

        if (show !== false) {
          if (this.fieldsType[type]) {
            if (type === 'TextInput') {
              return (
                <View
                  key={index}
                  style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}
                >
                  <View style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <View style={styles.inputContainer}>
                      <TextInput
                        style={styles.textInput}
                        {...otherProps}
                        placeholderTextColor={commonStyle.placeholderTextColor}
                        underlineColorAndroid={'transparent'}
                        editable={isEditable}
                        value={this.state[field.key] !== undefined && this.state[field.key] !== null && this.state[field.key].toString()}
                        onChangeText={value => {
                          this.state[field.key] = value
                          this.setState(this.state)
                          let _obj = {}
                          _obj[field.key] = value
                          this.props.onChange && this.props.onChange(_obj)
                        }}
                      />
                    </View>
                  </View>
                </View>
              )
            } else if (type === 'Button') {
              return (
                <View
                  key={index}
                  style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                  <View
                    style={[styles.content, isLastField ? styles.lastLine : null, {justifyContent: commonStyle.center}]}>
                    <Button
                      {...field}
                      {...otherProps}>
                      {field.text}
                    </Button>
                  </View>
                </View>
              )
            } else if (type === 'ButtonGroup') {
              return (
                <View
                  key={index}
                  style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                  <View style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <View style={{flex: 1, height: 49, flexDirection: commonStyle.row, alignItems: commonStyle.center, justifyContent: 'flex-end', marginRight: 10}}>
                      {
                        field.items.map((item, index) => {
                          let _cloneBtn = deepClone(item)
                          Object.keys(_cloneBtn).map((key, index) => {
                            if (key.indexOf('on') === 0) {
                              _cloneBtn[key] = this.props[_cloneBtn[key]]
                            }
                          })
                          if (typeof _cloneBtn.selected === 'boolean') {
                            return (
                              <Button
                                key={index}
                                style={[_cloneBtn.style, _cloneBtn.selected ? _cloneBtn.selectedStyle : null]}
                                textStyle={[_cloneBtn.textStyle, _cloneBtn.selected ? _cloneBtn.textSelectedStyle : null]}
                                {..._cloneBtn}
                              >
                                {_cloneBtn.text}
                              </Button>
                            )
                          } else {
                            return (
                              <Button
                                key={index}
                                style={[_cloneBtn.style, _cloneBtn.selected && _cloneBtn.selected() ? _cloneBtn.selectedStyle : null]}
                                textStyle={[_cloneBtn.textStyle, _cloneBtn.selected && _cloneBtn.selected() ? _cloneBtn.textSelectedStyle : null]}
                              >
                                {_cloneBtn.text}
                              </Button>
                            )
                          }
                        })
                      }
                    </View>
                  </View>
                </View>
              )
            } else if (type === 'Switch') {
              return (
                <View
                  key={index}
                  style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}
                >
                  <View style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <View style={styles.switch}>
                      <Switch
                        disabled={!isEditable}
                        value={this.state[field.key] !== undefined && this.state[field.key] !== null && this.state[field.key]}
                        onValueChange={value => {
                          this.state[field.key] = value
                          this.setState(this.state)
                          let _obj = {}
                          _obj[field.key] = value
                          this.props.onChange && this.props.onChange(_obj)
                        }}
                      />
                    </View>
                  </View>
                </View>
              )
            } else if (type === 'View') {
              return (
                <View key={index}
                      style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                  <View
                    key={index}
                    style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <View
                      ref={'customView'}
                      style={styles.view}
                      {...field}
                      {...otherProps}
                    >
                      {otherProps.view}
                    </View>
                  </View>
                </View>
              )
            } else if (type === 'TextArea') {
              let Comp = this.fieldsType[type]
              return (
                <View key={index}
                      style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                  <View
                    key={index}
                    style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <Comp
                      ref={(ref) => this._component[field.key] = ref}
                      name={field.key}
                      value={this.state}
                      editable={isEditable}
                      {...field}
                      {...otherProps}
                      onChange={this.props.onChange && this.props.onChange()}
                    />
                  </View>
                </View>
              )
            } else {
              let Comp = this.fieldsType[type]
              return (
                <View key={index}
                      style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                  <View
                    key={index}
                    style={[styles.content, isLastField ? styles.lastLine : null]}>
                    {
                      label ?
                        <View style={styles.leftPanel}>
                          <View style={styles.leftTitle}>
                            <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                            <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                          </View>
                          {
                            subTitle ?
                              <View style={styles.subTitle}>
                                <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                              </View> : null
                          }
                        </View> : null
                    }
                    <View style={{flex: 1}}>
                      <Comp
                        ref={(ref) => this._component[field.key] = ref}
                        name={field.key}
                        value={this.state}
                        editable={isEditable}
                        {...field}
                        {...otherProps}
                        descValue={field.name}
                        onChange={this.props.onChange && this.props.onChange()}
                      />
                    </View>
                  </View>
                </View>
              )
            }
          } else {
            return (
              <View key={index}
                    style={[styles.row, !isLastField ? {borderBottomWidth: 1, borderBottomColor: commonStyle.lineColor} : null]}>
                <View
                  key={index}
                  style={[styles.content, isLastField ? styles.lastLine : null]}>
                  {
                    label ?
                      <View style={styles.leftPanel}>
                        <View style={styles.leftTitle}>
                          <Text style={{fontSize: 15, color: commonStyle.textBlockColor}}>{label}</Text>
                          <Text style={{fontSize: 20, color: commonStyle.red}}>{subLabel}</Text>
                        </View>
                        {
                          subTitle ?
                            <View style={styles.subTitle}>
                              <Text style={{fontSize: 12, color: commonStyle.textGrayColor}}>{subTitle}</Text>
                            </View> : null
                        }
                      </View> : null
                  }
                  <View style={{ flex: 1, height: 49 }}>
                    <CustomAction
                      type={type}
                      ref={(ref) => this._component[field.key] = ref}
                      name={field.key} value={this.state}
                      {...field}
                      {...otherProps}
                      editable={isEditable}
                      onChange={this.props.onChange}
                      descValue={field.name}
                      />
                  </View>
                </View>
              </View>
            )
          }
        }
      }
    })
  }

详细的使用方式请参照项目源码OneM

https://github.com/guangqiang-liu/OneM

福利时间

上一篇下一篇

猜你喜欢

热点阅读