什么是受控组件与非受控组件?
描述 React 中受控组件和非受控组件的区别,包括它们的定义、特点及适用场景。
在 React 中,受控组件(Controlled Components)和非受控组件(Uncontrolled Components)是处理表单元素或用户输入的两种不同方式,核心区别在于数据管理的责任由 React 还是 DOM 本身承担。以下是详细介绍:
1. 受控组件(Controlled Components)
- 定义:受控组件的表单值完全由 React 组件状态管理。用户输入触发事件处理函数,更新 state,并通过重新渲染来同步 DOM 的值。所有数据流动由 React 控制,实现双向绑定。
- 关键特征:
- 值由
state
或props
直接控制(如将值绑定到输入框的value
属性)。 - 通过
onChange
等事件处理器更新状态。 - 易于实现表单验证、数据清洗和实时处理.
- 值由
- 代码示例:
import React, { useState } from 'react'; function ControlledInput() { const [inputValue, setInputValue] = useState(''); const handleChange = (e) => { setInputValue(e.target.value); }; return <input type="text" value={inputValue} onChange={handleChange} />; }
2. 非受控组件(Uncontrolled Components)
- 定义:非受控组件的值由 DOM 自身管理,而非 React state。值直接由用户输入设定,React 组件通常通过
ref
来读取当前值,但不能直接更新它,依赖于原生 HTML 行为. - 关键特征:
- 值由 DOM 引用获取(使用
ref
API),而不是绑定的 state。 - 数据流动是单向的,从用户输入到读取值。
- 代码更简洁,适用于不需要复杂状态交互的场景.
- 值由 DOM 引用获取(使用
- 代码示例:
import React, { useRef } from 'react'; function UncontrolledInput() { const inputRef = useRef(); const handleSubmit = () => { alert(inputRef.current.value); }; return ( <div> <input type="text" ref={inputRef} /> <button onClick={handleSubmit}>Submit</button> </div> ); }
3. 受控与非受控组件的主要区别
- 数据管理方式:
- 受控组件:数据流双向(state 绑定到 DOM,用户输入更新 state),React 负责同步.
- 非受控组件:数据流单向(依赖 ref 读取值),React 不干预状态变化.
- 控制力:
- 受控组件提供精准控制,适用于表单验证、动态 UI 或要求实时状态更新的场景(如搜索框过滤)。
- 非受控组件简化处理,适用于文件上传、输入范围控件或与第三方库集成,避免 React 过多状态干预.
- 性能与复杂度:
- 受控组件更重但可控性强,频繁状态更新可能导致较多 re-render;非受控组件更轻量,因 DOM 直接驱动,少 re-render.
4. 适用场景
- 使用受控组件:
- 场景:表单字段验证、动态更新其他组件状态、多步表单处理或需要访问 React 生命周期。
- 例如:在线编辑器或条件验证表单中,状态驱动提供统一管理.
- 使用非受控组件:
- 场景:简单表单提交、大文件输入按钮、快速原型开发或追求性能优化的环境.
- 例如:集成 jquery 等原生库时减少侵入性操作或优化减少 re-render 开销.
总的来说,在 React 应用中,选择受控组件利于控制和扩展;非受控组件适合简化开发流程。根据项目需求偏好切换处理方式。