利用装饰器简化代码,将表单验证操作统一到一个装饰器中进行
首先装饰器的定义为修饰器(Decorator)是一个函数,用来修改类的行为。
建立一个装饰器
export default (Comp) => {
class Cp extends Comp{
constructor(props){
super(props);
this.state = {
...this.state,
errors: {
},
// error queuq
this.errorQueue = {};
}
this.setEmailcode = this.setEmailcode.bind(this);
this.callError = this.callError.bind(this);
this.fIn = this.fIn.bind(this);
this.bOut = this.bOut.bind(this);
}
setEmailcode(v){
this._clearStateKey('emailcode', v);
if(v.target.value.length < 7){
this._changeHandler('emailcode', v);
}
}
ckemailcode(){
let rt = true;
const errors = [];
const KEY = 'gcode';
const intl = this.intl
this._isEmpty(this.state[KEY], errors, intl.formatMessage({id: "请输入谷歌验证码"}));
//验证是否符合规则,不符合则扔到errors队列中去
this._setError(KEY, errors);
return this._hasError(KEY);
}
_isEmpty(v, errors = [], msg = ''){
!v && errors.push(msg);
return !v;
}
_changeHandler(k, v){
const target = v.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
[k]: value
});
}
// flg is get code 1 is get code
_setError(k, v, flg = 0){
let { errors } = this.state,
cd = this._isArray(v) && v.length;
!this.errorQueue[k] && (this.errorQueue[k] = []);
this.errorQueue[k][flg] = cd ? v : [];
setTimeout(() => {
this.setState(prevState => {
return {
errors: {
...(prevState.errors),
[k]: cd ? (
errors[k] ? errors[k].unshift(...v) : errors[k] = [...v],
[...new Set(errors[k])]
) : [...(this.errorQueue[k].filter(v => {
return v.length > 0;
})[0] || [])],
}
}
});
},0);
}
_hasError(k = ''){
return !this.errorQueue[k].filter(v => v.length > 0).length;
}
callError(k, v){
this._setError(k, v?[v]:[], 1);
// keydown
const KEY = 'ky' + k;
if(this.state[KEY]){
this.setState({
[KEY]: 0
});
}
}
clearsError(k = [], flg = 0){
k.forEach(v => {
this._setError(v, "",flg);
});
return new Promise((r,e) => {
setTimeout(() => {
r(1);
})
})
}
changeImgCode() {
let now = +new Date;
this.props.changeImgCode(URL_IMG_CODE + "?t=" + now);
}
bOut(e){
const k = this._getTgKey(e);
if(this.state.focusBlu){
this.setState({
focusBlu:''
})
}
this.clearQueueKey(k);
this.hasError([k]);
this.Uc(k);
}
fIn(e){
const key = this._getTgKey(e);
key === 'password' && this.setState({
mvInPwd: 1
})
this._setError(key, []);
this._setError(key, [], 1);
}
_isEmpty(v, errors = [], msg = ''){
!v && errors.push(msg);
return !v;
}
return Cp;
}
在需要做表单验证的地方引入装饰器
import Form from '../../../decorator/form';
@Form
class WithdrawForm extends React.Component{
constructor(props){
super(props)
this.state = {
emailcode : "",
}
this.setFoucs = this.setFoucs.bind(this)
}
setFoucs(name){
this.setState({
focusBlu:name
})
}
renner(){
const {setEmailcode,bOut,fIn} = this
const {errors,ckFlg,emailcode} = this.state
const {emailcode:eemailcode = [] } = errors
return(
<div>
<div className={`${ckFlg && eemailcode[0] && 'err'} input_div_1 input_div_2`} style={{borderColor:focusBlu=='emailcode'?'#6687D3':''}}>
<input type="text" className="input_1 input_2" placeholder={formatMessage({id: "请输入邮箱验证码(水印)"})} onPaste={setEmailcode} autoComplete="off" value={emailcode} onChange={setEmailcode} name="emailcode" onFocus={(e)=>{this.setCk();this.setFoucs('emailcode');this.fIn(e)}} onBlur={bOut} />
</div>
<span className="ew">{ckFlg ? eemailcode[0] : null}</span>//错误提示信息
</div>
)
}
export default WithdrawForm
网友评论