@ozo/react-rock
Version:
React 移动端开发脚手架,基于CRA3,通用、开箱即用。
203 lines (181 loc) • 6.16 kB
JSX
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import shortid from 'shortid';
import CloseIcon from './components/CloseIcon';
import styles from './InputSingle.module.scss';
/**
* 输入组件
*/
class InputSingle extends Component {
static getDerivedStateFromProps(nextProps, prevState) {
const { value } = nextProps;
if (value) {
return {
showClose: true,
};
}
return null;
}
constructor(props) {
super(props);
this.state = {
showClose: false, // (props.value && !props.disabled) ? true : false
};
this.id = shortid.generate();
this.textInput = React.createRef();
}
componentWillUnmount() {
clearTimeout(this.debounceTimeout);
this.debounceTimeout = null;
}
/**
* @description 处理输入框 change 事件
* @param {dom} e 输入框 input元素
*/
/*eslint-disable-next-line complexity */
handleChange = (e) => {
const val = e.target.value;
let tRule = '';
let ruleCheckResult;
const { type = 'text', rule, maxLength, handleChange } = this.props;
// 正则检测
switch (type) {
case 'text': {
// 默认可包含中文、字符、数字、下划线
tRule = rule || `^[a-zA-Z0-9_\\u4e00-\\u9fa5]{0,${maxLength || 16}}$`;
break;
}
case 'number': {
// 默认匹配
const tMaxLength = maxLength || 10;
tRule = rule || `^(0|[1-9][0-9]{0,${tMaxLength}})([\\.]?|(\\.\\d{1,2}))?$`;
break;
}
case 'mobile': {
// 默认匹配1开头的数字
const tMaxLength = maxLength - 1 || 10;
tRule = rule || `^1([0-9]{0,${tMaxLength}})$`;
break;
}
case 'IDCard': {
// 身份证简单验证
tRule = `^[0-9]{0,${maxLength - 1 || 17}}([0-9]|X|x)$`;
break;
}
default: {
break;
}
}
const checker = new RegExp(tRule);
if (val && !checker.test(val)) {
return;
}
if (val) {
this.setState({ showClose: true });
} else {
this.setState({ showClose: false });
}
// 身份证单独验证
if (type === 'IDCard' && (val.length === 16 || val.length === 19)) {
ruleCheckResult = new RegExp(rule || '(^\\d{15}$)|(^\\d{17}([0-9]|X|x)$)').test(val);
} else if (val.length > 19) {
return;
}
handleChange && handleChange(val, ruleCheckResult);
};
/**
* @description 处理输入框 聚焦 事件
* @param {dom} e 输入框 input元素
*/
handleCloseShowOnFocus = (e) => {
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout);
this.debounceTimeout = null;
}
e.target.value && this.setState({ showClose: true });
};
handleCloseHideOnBlur = () => {
this.debounceTimeout = setTimeout(() => {
this.setState({ showClose: false });
}, 150);
};
handleCloseClick = () => {
const { handleChange } = this.props;
handleChange && handleChange('');
this.focusTextInput();
this.setState({ showClose: false });
};
focusTextInput = () => {
this.textInput.current.focus();
};
render() {
const {
label,
type,
originType,
value,
className,
inputClass,
handleChange,
size,
labelStyle,
labelFor,
required,
...tProps
} = this.props;
const { showClose } = this.state;
return (
<div className={`inputItemFix ${styles.inputItem} ${styles[size] || ''} ${className || ''}`}>
<label htmlFor={labelFor || this.id}>
{label && (
<span className={styles.label} style={labelStyle}>
{label}
{required && (
<span className={styles.required}>{typeof required === 'string' ? required : '*'}</span>
)}
</span>
)}
<input
id={labelFor || this.id}
type={originType || 'text'}
className={inputClass}
value={value}
onChange={this.handleChange}
onFocus={this.handleCloseShowOnFocus}
onBlur={this.handleCloseHideOnBlur}
autoComplete="off"
pattern={type === 'mobile' ? '[0-9]*' : ''}
ref={this.textInput}
{...tProps}
/>
</label>
{showClose && <CloseIcon handleClick={this.handleCloseClick} />}
</div>
);
}
}
InputSingle.propTypes = {
// 输入框类型,默认值:text
type: PropTypes.oneOf(['text', 'number', 'mobile', 'IDCard']),
// 输入框的label,必传
label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
// 是否必填
required: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
// Label for的值
labelFor: PropTypes.string,
// 占位文字
placeholder: PropTypes.string,
// 叠加的css类名
className: PropTypes.string,
// 自定义input框样式
inputClass: PropTypes.string,
// 是否允许输入
disabled: PropTypes.bool,
// 输入框的值,受控
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// 允许输入最大长度
maxLength: PropTypes.number,
// value改变回调
handleChange: PropTypes.func,
};
export default InputSingle;