受控组件和非受控组件的区别

发布于:2025-04-01 ⋅ 阅读:(23) ⋅ 点赞:(0)

在 React 中,​受控组件(Controlled Components)​ 和 ​非受控组件(Uncontrolled Components)​ 是处理表单元素的两种不同方式,它们的核心区别在于 ​数据管理的方式 和 ​与 React 的交互模式。

受控组件(Controlled Components)

定义

表单元素(如 <input><textarea><select>)的值由 ​Reactstate 完全控制。用户输入会触发 React 的状态更新,表单的当前值始终与 Reactstate 同步。

关键特征

  • 数据流:单向绑定(从 React state 到 DOM)。
  • 更新方式:通过 onChange 事件手动更新 state。
  • 值的来源:组件的 value 或 checked 属性直接绑定到 state。

代码示例

import { useState } from 'react';

function ControlledForm() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (e) => {
    setInputValue(e.target.value); // 手动同步到 state
  };

  return (
    <input
      type="text"
      value={inputValue} // 值由 React state 控制
      onChange={handleChange}
    />
  );
}

适用场景

  • 需要实时验证输入(如密码强度检查)。
  • 动态表单(如根据输入内容显示其他字段)。
  • 强制输入格式(如只能输入数字)。

优点

  • 完全控制表单数据,确保 React state 是唯一数据源。
  • 支持复杂的交互逻辑(如输入时实时反馈)。

缺点

  • 代码量较多(需要为每个表单元素编写事件处理函数)。
  • 频繁的 state 更新可能导致性能问题(大型表单需优化)。

非受控组件(Uncontrolled Components)

定义

表单元素的值由 ​DOM 自身管理,React 通过 ref 在需要时(如表单提交时)直接读取 DOM 的值。用户输入不会触发 React 的状态更新。

关键特征

  • 数据流:直接操作 DOM。
  • 更新方式:通过 ref 手动获取值。
  • 值的来源:DOM 节点的当前值。

代码示例

import { useRef } from 'react';

function UncontrolledForm() {
  const inputRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(inputRef.current.value); // 通过 ref 获取 DOM 值
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        ref={inputRef} // 使用 ref 关联 DOM 节点
        defaultValue="初始值" // 仅初始化时设置默认值
      />
      <button type="submit">提交</button>
    </form>
  );
}

适用场景

  • 简单表单(不需要实时验证或动态交互)。
  • 文件上传(<input type="file"> 必须用非受控组件)。
  • 性能敏感场景(避免频繁 state 更新)。

优点

  • 代码简洁,无需管理状态。
  • 性能更好(减少渲染次数)。

缺点

  • 无法实时控制数据(如强制输入格式)。
  • 不符合 React 的“单一数据源”原则。

核心区别对比

特性 受控组件 非受控组件
数据管理 React state 控制 DOM 自身管理
值同步 实时同步(onChange 事件) 手动获取(通过 ref)
初始值设置 通过 value 属性 通过 defaultValue 属性
表单验证时机 输入时实时验证 提交时验证
代码复杂度 较高(需处理事件和状态) 较低(直接操作 DOM)
性能 可能较低(频繁渲染) 较高
React 哲学匹配度 高(符合单向数据流) 低(依赖 DOM 操作)

如何选择

  1. 优先受控组件:

大多数场景推荐使用受控组件,尤其是需要实时交互、验证或动态表单时。

  1. 非受控组件的合理场景:
  • 文件上传(<input type="file">)。
  • 性能敏感且无需实时反馈的表单。
  • 与非 React 的第三方库集成(如富文本编辑器)。

注意点

  1. 文件输入

<input type="file"> 必须用非受控组件,因为其值只能由用户设置(安全限制)。

  1. 默认值:

非受控组件用 defaultValuedefaultChecked 设置初始值(类似原生 HTML)。

  1. 受控组件的性能优化:

大型表单中避免频繁渲染,可通过防抖(debounce)或 useCallback 优化事件处理函数。

总结

  • ​受控组件:数据由 React 完全控制,适合复杂交互。
  • 非受控组件:数据由 DOM 管理,适合简单场景或性能敏感需求。

根据实际需求选择,优先遵循 React 的单向数据流原则,仅在必要时使用非受控组件。


网站公告

今日签到

点亮在社区的每一天
去签到