Skip to content
 

受控组件和非受控组件

更新: 9/26/2025字数: 0 字 时长: 0 分钟

一、核心概念区分

1. 受控组件 (Controlled Components)

  • 定义:表单数据由 React 组件状态完全控制
  • 特点
    • 表单值存储在 state 中
    • 通过 onChange 事件更新 state
    • 数据流是单向的(state → 表单)
jsx
function ControlledForm() {
  const [value, setValue] = useState("");

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  return <input value={value} onChange={handleChange} />;
}

2. 非受控组件 (Uncontrolled Components)

  • 定义:表单数据由 DOM 自身管理
  • 特点
    • 通过 ref 访问 DOM 元素获取值
    • 表单保持自己的内部状态
    • 更适合与非 React 代码集成
jsx
function UncontrolledForm() {
  const inputRef = useRef(null);

  const handleSubmit = () => {
    console.log(inputRef.current.value);
  };

  return (
    <>
      <input ref={inputRef} defaultValue="" />
      <button onClick={handleSubmit}>提交</button>
    </>
  );
}

二、技术实现对比

1. 值控制方式

特性受控组件非受控组件
值绑定value={state}defaultValue=""
值获取直接从 state 读取需要通过 ref 访问 DOM
状态更新onChange 事件触发更新DOM 自动管理

2. 常见表单元素处理

jsx
// 受控组件示例集合
function ControlledComponents() {
  const [text, setText] = useState("");
  const [isChecked, setIsChecked] = useState(false);
  const [selectedOption, setSelectedOption] = useState("option1");

  return (
    <>
      {/* 文本输入 */}
      <input type="text" value={text} onChange={(e) => setText(e.target.value)} />

      {/* 复选框 */}
      <input type="checkbox" checked={isChecked} onChange={(e) => setIsChecked(e.target.checked)} />

      {/* 单选按钮 */}
      <select value={selectedOption} onChange={(e) => setSelectedOption(e.target.value)}>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
      </select>
    </>
  );
}

三、选择时机与场景分析

1. 优先使用受控组件的情况

  • 需要实时验证输入
  • 根据输入动态禁用/启用提交按钮
  • 强制特定输入格式
  • 实现复杂表单逻辑
jsx
// 实时验证示例
function EmailInput() {
  const [email, setEmail] = useState("");
  const [isValid, setIsValid] = useState(false);

  const handleChange = (e) => {
    const value = e.target.value;
    setEmail(value);
    setIsValid(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value));
  };

  return (
    <>
      <input type="email" value={email} onChange={handleChange} />
      {!isValid && <span>请输入有效的邮箱地址</span>}
    </>
  );
}

2. 考虑非受控组件的情况

  • 表单非常简单且不需要即时验证
  • 需要集成第三方 DOM 库
  • 处理大型表单性能敏感时
  • 文件上传 <input type="file"> (总是非受控)
jsx
// 文件上传示例
function FileUpload() {
  const fileInput = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(fileInput.current.files[0]);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="file" ref={fileInput} />
      <button type="submit">上传</button>
    </form>
  );
}

我见青山多妩媚,料青山见我应如是。