受控组件 vs 非受控组件
聊聊表单数据到底归谁管
先说人话:这两种模式的区别就是——表单的值到底归 React 管,还是归 DOM 自己管。
就这一句话,核心区别就在这。
受控组件:React 当家作主
什么是受控组件?
就是表单的值由 React 的 state 完全控制。你输入一个字,state 变一次,组件重新渲染一次。
怎么写?
工作流程:
- 用户打字 -> 触发
onChange onChange调用setState更新 state- state 变了 -> 组件重新渲染
- 重新渲染后,
value={value}把新值塞回输入框
有啥优点?
- 数据随时可控:state 就是"唯一真相",随时可以拿到最新值
- 验证/格式化方便:每次输入都能拦截,想咋处理输入都行
- 编程式控制:想重置输入?
setValue("")就行;想设值?setValue("hello")就搞定 - 符合 React 套路:数据自上而下流动,清楚明白
有啥缺点?
每次输入都触发 setState、重新渲染,性能上可能有点浪费——不过对于大多数场景,这点开销可以忽略不计。
非受控组件:DOM 自己管自己
什么是非受控组件?
表单的值由 DOM 自己管理,React 不管。React 想要值的时候,通过 ref 去 DOM 节点"拉取"。
怎么写?
有啥优点?
- 更像原生 HTML:写法跟普通表单一样
- 代码更简单:不用写 onChange,不用写 setState
- 性能更好:每次输入不触发 React 渲染
- 集成第三方库方便:有些库要自己操作 DOM,用 ref 直接拿到节点,很顺滑
有啥缺点?
- 数据不可控:你想在用户输入过程中做验证?难
- 想重置值?麻烦:得手动操作 DOM,违背了 React 的套路
- 不知道当前值是啥:除非你去 ref 里拿
到底该用哪个?
大多数情况下,用受控组件。
React 官方推荐受控组件,因为数据可控、逻辑清晰、符合 React 思想。
用受控组件的情况:
- 需要即时验证输入(密码强度、格式校验)
- 需要根据输入动态控制其他 UI(输入为空时禁用提交按钮)
- 需要强制格式化(比如自动转大写、格式化手机号)
- 表单逻辑复杂,多个字段相互依赖
- 需要编程式重置或赋值
用非受控组件的情况:
- 表单极其简单,只需要在提交时拿一次值
- 要接第三方库(图片上传、富文本编辑器),它们自己要操作 DOM
- 输入极其频繁(比如实时绘图中选颜色),性能实在敏感
总结
记住一句话:React 能管的就用受控组件,React 管不了的或者不想管的,就用非受控组件。

