React16.13 簡(jiǎn)單封裝一個(gè)input組件

React16.13 簡(jiǎn)單封裝一個(gè)input組件

input組件

  1. GInput.jsx
import React from 'react'
import './GInput.css'
// props 參數(shù):
// --props 
// ------可選:type defaultValue placeholder readOnly disabled
// ------可選:trim:"true" 過濾前后空格 className
// ------可選:rule:{ regx:RegExp | function, [callback: function, errorMsg: ''] } 驗(yàn)證規(guī)則
// ------必選:onInput input事件函數(shù),通過這個(gè)函數(shù)獲取修改后的input值value
// --自定義屬性以data-*方式定義
class GInput extends React.Component {
  constructor (props) {
    super();
    let errMsg = ''
    if (props.rule) {
      errMsg = props.rule.errorMsg || ''
    }
    let attrs = {}
    attrs = this.getOptionsAttrs(props)
    this.state = {
      val: null,
      attrs: attrs,
      className: props.className || '',
      hasError: this.regxRule(props, props.defaultValue || props.value),
      errorMsg: errMsg
    }
    this.handleInputChange = this.handleInputChangeFn.bind(this)
  }
  hasRule (props) {
    let flag = ''
    if (props.rule) {
      if (props.rule.regx instanceof RegExp) {
        flag = 'RegExp'
      }
      else if (typeof props.rule.regx === 'function') {
        flag = 'function'
      }
    }
    return flag
  }
  regxRule (props, expValue) {
    expValue = expValue || ''
    // console.log('expValue:', expValue, '  flag:', props.rule.regx.test(expValue))
    let error = false
    let ruleFlag = this.hasRule(props)
    if (ruleFlag) {
      let flag;
      if(ruleFlag === 'RegExp') {
        flag = new RegExp(props.rule.regx).test(expValue)
      }
      else if (ruleFlag === 'function') {
        flag = props.rule.regx(expValue)
      }
      if (!flag) {
        error = true
      }
      if (typeof props.rule.callback === 'function') {
        props.rule.callback(flag)
      }
    }
    return error
  }
  handleInputChangeFn(event) {
    // console.log(event.target.value)
    let val = event.target.value
    if (typeof this.props.onInput === 'function') {
      if(this.props.trim === 'true') {
        val = val.replace(/^\s*|\s*$/g,'')
        event.target.value = val
      }
      if (typeof val === 'string' && val !== this.state.val) {
        // 如果設(shè)置了trim:"true",每次輸入空格的時(shí)候,都會(huì)過濾,value一直都是''
        // 這種情況下,只需要第一次更新一下空值,后面的空值就不需要再更新了
        // 下面的代碼就是為了達(dá)到這個(gè)目的,防止每次空值都更新
        this.props.onInput(val)
        this.setState({
          val: val
        })
      }
      this.setState({
        hasError: this.regxRule(this.props, val)
      })
    } else {
      console.error('<GInput> has no onInput event.')
    }
  }
  // type onInput className value屬性是直接寫在input標(biāo)簽中的,rule, trim屬性是不需要直接寫在屬性中的
  // 其他的屬性,包括自定義屬性,都以 attrs 解構(gòu)賦值的方式寫入input屬性中
  getOptionsAttrs (props) {
    let obj = {}
    let keyArr = Object.keys(props)
    let requiredOptions = 'onInput|type|rule|trim|className|value'
    let key = ''
    for(let i = 0; i < keyArr.length; i++) {
      key = keyArr[i]
      if(requiredOptions.indexOf(key) > -1) {
        continue
      }
      // console.log(key)
      obj[key] = props[key]
    }
    return obj
  }
  render () {
    return (
      <div className={'g-input-box ' + this.state.className + (this.state.hasError? ' error':'')}>
        {/* <input className='g-input'
               readOnly={this.state.readOnly}
               disabled={this.state.disabled}
               type={this.props.type || 'text'}
               placeholder={this.props.placeholder}
               defaultValue={this.props.defaultValue}
               onInput={this.handleInputChange}/> */}
        {
          this.props.value ?
          (
            <input className='g-input'
               {...this.state.attrs}
               type={this.props.type || 'text'}
               value={this.props.value}
               onInput={this.handleInputChange}/>
          )
          :
          (
            <input className='g-input'
               {...this.state.attrs}
               type={this.props.type || 'text'}
               onInput={this.handleInputChange}/>
          )
        }
        {
          this.state.hasError && (
            <div className="error-msg">{this.state.errorMsg}</div>
          )
        }
      </div>
    )
  }
}

export default GInput;

組件同目錄下的樣式

html, body {
  height: 100%; padding: 0; margin: 0;
}
/*GInput*/
.g-input-box > .g-input {
  border: 1px solid #666;
}
.g-input-box.error > .g-input {
  border: 1px solid #f00;
}
.g-input-box.error > .error-msg, .g-input-box.error > .g-input {
  color: #f00;
}

組件的引用頁(yè)面

import React, { Component } from "react";
import GInput from './components/form/GInput.jsx'

class About extends Component {
  constructor(props) {
    super();
    this.state={
      form: {
        input123: 'abc',
        pwd: '12s3'
      },
      rules: {
        input123Rule: {
          regx: /^[a-z]*$/g,
          callback: function (flag) {
            console.log('input123Rule:', flag)
          }
        },
        pwdRule: {
          regx: function (val) {
            if (val > 100 && val < 10000) {
              return true
            } else {
              return false
            }
          },
          callback: function (flag) {
            console.log('pwdRule:', flag)
          },
          errorMsg: '只能輸入100-10000之間的數(shù)字'
        }
      }
    }
  }
  UNSAFE_componentWillMount () {}
  componentDidMount () {}
  handleInput123Change (val) {
    console.log('handleInput123Change:', val)
  }
  render () {
    return (
      <div>
        <h1>About page</h1>

        <GInput type="text" className="my-input-123"
                trim={true}
                disabled={false}
                placeholder="只能輸入小寫字母"
                rule={this.state.rules.input123Rule}
                onInput={this.handleInput123Change}></GInput>
        <GInput type="text" className="my-input-123"
                trim={true}
                defaultValue={this.state.form.pwd}
                rule={this.state.rules.pwdRule}
                onInput={this.handleInput123Change}></GInput>
      </div>
    )
  }
}
export default About;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容