Skip to content

事件处理与表单绑定

在 React 中,事件处理和表单绑定是构建交互式应用的重要部分。本章节将介绍 React 中的事件处理方式和表单绑定方法。

7.1 React 事件绑定语法

React 中的事件绑定与 HTML 中的事件绑定类似,但有一些语法差异:

  • React 事件使用驼峰命名法(如 onClick 而不是 onclick
  • React 事件处理函数是作为属性传递的,而不是字符串

基本语法

jsx
<button onClick={handleClick}>点击我</button>
<input onChange={handleChange} />

常用事件

  • 鼠标事件onClickonMouseOveronMouseOutonMouseDownonMouseUp
  • 键盘事件onKeyDownonKeyUponKeyPress
  • 表单事件onChangeonSubmitonFocusonBlur
  • 触摸事件onTouchStartonTouchMoveonTouchEnd

7.2 事件处理函数的几种写法

1. 箭头函数(推荐)

jsx
function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

2. 函数声明

jsx
function Counter() {
  const [count, setCount] = useState(0);

  function handleIncrement() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={handleIncrement}>增加</button>
    </div>
  );
}

3. 类组件中的方法(了解即可)

jsx
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    // 绑定 this
    this.handleIncrement = this.handleIncrement.bind(this);
  }

  handleIncrement() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>计数:{this.state.count}</p>
        <button onClick={this.handleIncrement}>增加</button>
      </div>
    );
  }
}

7.3 事件对象 e 的使用

React 中的事件对象是一个合成事件(SyntheticEvent),它是 React 对浏览器原生事件的封装。

基本使用

jsx
function handleClick(e) {
  e.preventDefault(); // 阻止默认行为
  e.stopPropagation(); // 阻止事件冒泡
  console.log('点击了按钮');
}

return <button onClick={handleClick}>点击我</button>;

常用方法

  • e.preventDefault():阻止默认行为(如表单提交、链接跳转)
  • e.stopPropagation():阻止事件冒泡
  • e.target:获取触发事件的元素
  • e.currentTarget:获取绑定事件的元素

示例

jsx
function handleSubmit(e) {
  e.preventDefault(); // 阻止表单默认提交行为
  console.log('表单提交');
}

return (
  <form onSubmit={handleSubmit}>
    <button type="submit">提交</button>
  </form>
);

7.4 表单绑定

受控组件(推荐)

受控组件是指表单元素的值由 React 状态控制的组件。

文本框绑定

jsx
import { useState } from 'react';

function TextInput() {
  const [value, setValue] = useState('');

  function handleChange(e) {
    setValue(e.target.value);
  }

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={handleChange}
        placeholder="请输入文本"
      />
      <p>输入值:{value}</p>
    </div>
  );
}

复选框绑定

jsx
import { useState } from 'react';

function Checkbox() {
  const [checked, setChecked] = useState(false);

  function handleChange(e) {
    setChecked(e.target.checked);
  }

  return (
    <div>
      <input
        type="checkbox"
        checked={checked}
        onChange={handleChange}
      />
      <label>{checked ? '已勾选' : '未勾选'}</label>
    </div>
  );
}

单选框绑定

jsx
import { useState } from 'react';

function RadioButtons() {
  const [gender, setGender] = useState('male');

  function handleChange(e) {
    setGender(e.target.value);
  }

  return (
    <div>
      <input
        type="radio"
        id="male"
        name="gender"
        value="male"
        checked={gender === 'male'}
        onChange={handleChange}
      />
      <label htmlFor="male">男</label>
      <input
        type="radio"
        id="female"
        name="gender"
        value="female"
        checked={gender === 'female'}
        onChange={handleChange}
      />
      <label htmlFor="female">女</label>
      <p>选择的性别:{gender}</p>
    </div>
  );
}

下拉框绑定

jsx
import { useState } from 'react';

function Select() {
  const [selected, setSelected] = useState('option1');

  function handleChange(e) {
    setSelected(e.target.value);
  }

  return (
    <div>
      <select value={selected} onChange={handleChange}>
        <option value="option1">选项 1</option>
        <option value="option2">选项 2</option>
        <option value="option3">选项 3</option>
      </select>
      <p>选择的值:{selected}</p>
    </div>
  );
}

多表单元素的统一管理

jsx
import { useState } from 'react';

function Form() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    password: '',
    remember: false,
    gender: 'male'
  });

  function handleChange(e) {
    const { name, value, type, checked } = e.target;
    setFormData(prevData => ({
      ...prevData,
      [name]: type === 'checkbox' ? checked : value
    }));
  }

  function handleSubmit(e) {
    e.preventDefault();
    console.log('表单数据:', formData);
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>姓名:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
        />
      </div>
      <div>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
      </div>
      <div>
        <label>密码:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
      </div>
      <div>
        <input
          type="checkbox"
          id="remember"
          name="remember"
          checked={formData.remember}
          onChange={handleChange}
        />
        <label htmlFor="remember">记住我</label>
      </div>
      <div>
        <input
          type="radio"
          id="male"
          name="gender"
          value="male"
          checked={formData.gender === 'male'}
          onChange={handleChange}
        />
        <label htmlFor="male">男</label>
        <input
          type="radio"
          id="female"
          name="gender"
          value="female"
          checked={formData.gender === 'female'}
          onChange={handleChange}
        />
        <label htmlFor="female">女</label>
      </div>
      <button type="submit">提交</button>
    </form>
  );
}

7.5 非受控组件

非受控组件是指表单元素的值由 DOM 本身管理的组件,通常使用 ref 来获取表单值。

基本使用

jsx
import { useRef } from 'react';

function UncontrolledForm() {
  const nameRef = useRef(null);
  const emailRef = useRef(null);

  function handleSubmit(e) {
    e.preventDefault();
    console.log('姓名:', nameRef.current.value);
    console.log('邮箱:', emailRef.current.value);
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>姓名:</label>
        <input type="text" ref={nameRef} />
      </div>
      <div>
        <label>邮箱:</label>
        <input type="email" ref={emailRef} />
      </div>
      <button type="submit">提交</button>
    </form>
  );
}

受控组件 vs 非受控组件

特性受控组件非受控组件
数据管理React 状态DOM 本身
实时验证支持不支持
表单重置简单复杂
性能可能较低(频繁渲染)较高
适用场景大多数表单简单表单、文件上传

实战练习

练习1:简单计数器

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <button onClick={() => setCount(count - 1)}>减少</button>
      <button onClick={() => setCount(0)}>重置</button>
    </div>
  );
}

练习2:表单验证

jsx
import { useState } from 'react';

function LoginForm() {
  const [formData, setFormData] = useState({
    email: '',
    password: ''
  });
  const [errors, setErrors] = useState({});

  function handleChange(e) {
    const { name, value } = e.target;
    setFormData(prevData => ({
      ...prevData,
      [name]: value
    }));

    // 清除错误
    if (errors[name]) {
      setErrors(prevErrors => ({
        ...prevErrors,
        [name]: ''
      }));
    }
  }

  function validateForm() {
    const newErrors = {};

    if (!formData.email) {
      newErrors.email = '请输入邮箱';
    } else if (!/+@+\.+/.test(formData.email)) {
      newErrors.email = '请输入有效的邮箱地址';
    }

    if (!formData.password) {
      newErrors.password = '请输入密码';
    } else if (formData.password.length < 6) {
      newErrors.password = '密码长度至少为 6 位';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  }

  function handleSubmit(e) {
    e.preventDefault();
    if (validateForm()) {
      console.log('登录成功', formData);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
        {errors.email && <p style={{ color: 'red' }}>{errors.email}</p>}
      </div>
      <div>
        <label>密码:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
        {errors.password && <p style={{ color: 'red' }}>{errors.password}</p>}
      </div>
      <button type="submit">登录</button>
    </form>
  );
}

练习3:搜索框

jsx
import { useState } from 'react';

function Search() {
  const [searchTerm, setSearchTerm] = useState('');
  const [results, setResults] = useState([]);

  function handleChange(e) {
    setSearchTerm(e.target.value);
  }

  function handleSubmit(e) {
    e.preventDefault();
    // 模拟搜索
    const mockResults = [
      `搜索结果 1: ${searchTerm}`,
      `搜索结果 2: ${searchTerm}`,
      `搜索结果 3: ${searchTerm}`
    ];
    setResults(mockResults);
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={searchTerm}
          onChange={handleChange}
          placeholder="请输入搜索内容"
        />
        <button type="submit">搜索</button>
      </form>
      <div>
        <h3>搜索结果:</h3>
        <ul>
          {results.map((result, index) => (
            <li key={index}>{result}</li>
          ))}
        </ul>
      </div>
    </div>
  );
}

通过本章节的学习,你已经掌握了 React 中的事件处理和表单绑定方法。这些知识是构建交互式 React 应用的基础,对于开发实际项目非常重要。

© 2026 编程马·菜鸟教程 版权所有