我们的现在可以在应用里添加用户了。但是还存在不小的问题:
用户可以输入任意长的名字 用户可以输入任意的年龄 用户可以不选择性别盲目信任用户输入的数据,会给系统埋下不小的隐患。这回我们就来把这隐患扼杀在摇篮之中。
表单验证无非就是对用户输入的数据进行有效性、非空性验证,验证失败会在相应的地方显示错误信息,并阻止用户提交表单。
我们需要记录每一个字段当前的有效状态,有效时隐藏错误信息,无效时显示错误信息。
而这个有效/无效,可以在表单值改变的时候进行判断。
我们对/src/pages/UserAdd.js进行修改:
首先修改了state的结构,把每个表单的值都放到了一个form字段中,方便统一管理;然后每个表单的值都变为了一个包含valid和value还有error字段的对象,valid表示该值的有效状态,value表示该表单具体的值,error表示错误提示信息:
... constructor () { super(); this.state = { form: { name: { valid: false, value: '', error: '' }, age: { valid: false, value: 0, error: '' }, gender: { valid: false, value: '', error: '' } } }; } ...
在handleValueChange方法中,根据参数field获取state中对应表单的对象,然后根据新的值value判断新的值是否有效,将新的值和新的有效状态更新到state里。
... handleValueChange (field, value, type = 'string') { if (type === 'number') { value = +value; } const { form } = this.state; const fieldObj = form[field]; // React要求不能直接对state进行修改 // 这里先对原来state中的对象进行拷贝 // 否则后续修改valid和value或者error的时候会影响到原来的state const newFieldObj = {...fieldObj, value}; switch (field) { case 'name': { if (value.length >= 5) { newFieldObj.error = '用户名最多4个字符'; newFieldObj.valid = false; } else if (value.length === 0) { newFieldObj.error = '请输入用户名'; newFieldObj.valid = false; } break; } case 'age': { if (value > 100 || value <= 0) { newFieldObj.error = '请输入1~100之间的数字'; newFieldObj.valid = false; } break; } case 'gender': { if (!value) { newFieldObj.error = '请选择性别'; newFieldObj.valid = false; } break; } } this.setState({ form: { ...form, [field]: newFieldObj } }); } ...
在handleSubmit方法中对每个字段的valid进行检测,如果有一个valid为false则直接return以中断提交操作。
... handleSubmit (e) { e.preventDefault(); const {form: {name, age, gender}} = this.state; if (!name.valid || !age.valid || !gender.valid) { alert('请填写正确的信息后重试'); return; } ... } ...
最后,也要对render方法进行更新:
render () { const {form: {name, age, gender}} = this.state; return ( <div> <header> <h1>添加用户</h1> </header> <main> <form onSubmit={(e) => this.handleSubmit(e)}> <label>用户名:</label> <input type="text" value={name.value} onChange={(e) => this.handleValueChange('name', e.target.value)} /> {!name.valid && <span>{name.error}</span>} <br/> <label>年龄:</label> <input type="number" value={age.value || ''} onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} /> {!age.valid && <span>{age.error}</span>} <br/> <label>性别:</label> <select value={gender.value} onChange={(e) => this.handleValueChange('gender', e.target.value)} > <option value="">请选择</option> <option value="male">男</option> <option value="female">女</option> </select> {!gender.valid && <span>{gender.error}</span>} <br/> <br/> <input type="submit" value="提交"/> </form> </main> </div> ); }
来看一下最终效果:
基本的表单验证就完成了!