react 项目实战(三)表单验证

我们需要记录每一个字段当前的有效状态,有效时隐藏错误信息,无效时显示错误信息

而这个有效/无效,可以在表单值改变的时候进行判断。

我们对/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 newFieldObj = {value, valid: true, error: ''};

  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 || !value) {
        newFieldObj.error = '请输入1~100之间的数字';
        newFieldObj.valid = false;
      }
      break;
    }
    case 'gender': {
      if (!value) {
        newFieldObj.error = '请选择性别';
        newFieldObj.valid = false;
      }
      break;
    }
    default: {
      //
    }
  }

  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;
  }

  fetch('http://localhost:3000/user', {
    method: 'post',
    body: JSON.stringify({
      name: name.value,
      age: age.value,
      gender: gender.value
    }),
    headers: {
      'Content-Type': 'application/json'
    }
  })
    .then((res) => res.json())
    .then((res) => {
      if (res.id) {
        alert('添加用户成功');
      } else {
        alert('添加失败');
      }
    })
    .catch((err) => console.error(err));
}
...

最后,也要对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>
  );
}

来看一下最终效果: 

注:完整代码 src / pages / UserAdd.js

import React from 'react';

// 添加用户组件
class UserAdd extends React.Component {
  // 构造器
  constructor(props) {
    super(props);
    // 定义初始化状态
    this.state = {
      form: {
        name: {
          valid: false, // 有效状态
          value: '', // 表单具体的值
          error: '' // 错误提示信息
        },
        age: {
          valid: false,
          value: '',
          error: ''
        },
        gender: {
          valid: false,
          value: '',
          error: ''
        }
      }
    };
  }
  // 输入框改变事件
  handleValueChange(field, value, type='string') {
    // 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型
    if(type === 'number'){
      value = + value;
    }
    // 定义常量
    const { form } = this.state;
    const newFieldObj = {value, valid: true, error: ''};
    // 判断
    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 || !value){
          newFieldObj.error = '请输入1~100之间的数字';
          newFieldObj.valid = false;
        }
        break;
      }
      case 'gender': {
        if(!value){
          newFieldObj.error = '请选择性别';
          newFieldObj.valid = false;
        }
        break;
      }
      default: {
        //
      }
    }

    // 设置状态
    this.setState({
      form: {
        ...form,
        [field]: newFieldObj
      }
    });
  }
  // 按钮提交事件
  handleSubmit(e){
    // 阻止表单submit事件自动跳转页面的动作
    e.preventDefault();
    // 定义常量
    const { form: { name, age, gender }} = this.state;
    // 验证
    if(!name.valid || !age.valid || !gender.valid){
      alert('请填写正确的信息后重试');
      return;
    }
    // 发送请求
    fetch('http://localhost:8000/user', {
      method: 'post',
      // 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
      body: JSON.stringify({
        name: name.value,
        age: age.value,
        gender: gender.value
      }),
      headers: {
        'Content-Type': 'application/json'
      }
    })
    // 强制回调的数据格式为json
    .then((res) => res.json())
    // 成功的回调
    .then((res) => {
      // 当添加成功时,返回的json对象中应包含一个有效的id字段
      // 所以可以使用res.id来判断添加是否成功
      if(res.id){
        alert('添加用户成功!');
      }else{
        alert('添加用户失败!');
      }
    })
    // 失败的回调
    .catch((err) => console.error(err));
  }
  
  render() {
    // 定义常量
    const {form: {name, age, gender}} = this.state;
    return (
      <div>
        <header>
          <div>添加用户</div>
        </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>
    );
  }
}

export default UserAdd;

.

posted @ 2018-02-23 15:30  每天都要进步一点点  阅读(2571)  评论(0编辑  收藏  举报