大家好,我是小杨。今天想和大家聊聊React开发中三个特别重要但又容易混淆的概念:高阶组件、受控组件和非受控组件。记得我刚学React时,经常被这几个名词搞得头晕眼花,直到在实际项目中踩了不少坑,才真正理解它们的区别和用法。
通过这篇文章,我会用最接地气的方式,带你彻底搞懂这三个"组件兄弟",保证让你看完后不再confused!
一、先来认识一下这三兄弟
简单来说:
- 高阶组件(HOC) :像是组件的"包装纸",用来增强组件功能
- 受控组件(Controlled Component) :表单数据由React state完全控制
- 非受控组件(Uncontrolled Component) :表单数据由DOM自身管理
下面我分别用代码示例来展示它们的用法和区别。
二、高阶组件:组件的超级装饰器
高阶组件其实就是一个函数,它接收一个组件,返回一个新的增强版组件。我最常用它来做代码复用和逻辑抽象。
来看个简单的例子:我要给多个组件添加用户认证功能
javascript
// 高阶组件:withAuth
const withAuth = (WrappedComponent) => {
return class AuthenticatedComponent extends React.Component {
state = {
isAuthenticated: false
};
componentDidMount() {
// 模拟检查用户登录状态
const userToken = localStorage.getItem('userToken');
this.setState({ isAuthenticated: !!userToken });
}
render() {
if (!this.state.isAuthenticated) {
return <div>请先登录!</div>;
}
return <WrappedComponent {...this.props} />;
}
};
};
// 使用高阶组件
const UserProfile = ({ userName }) => {
return <div>欢迎, {userName}!</div>;
};
const AuthenticatedUserProfile = withAuth(UserProfile);
// 在App中使用
const App = () => {
return (
<div>
<AuthenticatedUserProfile userName="小杨" />
</div>
);
};
高阶组件的好处是:逻辑复用,我可以在多个组件间共享认证逻辑,而不需要重复代码。
三、受控组件:React的乖孩子
受控组件的意思是:表单数据完全由React的state来控制。每次用户输入时,都会触发state更新,然后重新渲染组件。
这是我平时最常用的方式:
javascript
class LoginForm extends React.Component {
state = {
username: '',
password: ''
};
handleInputChange = (event) => {
const { name, value } = event.target;
this.setState({
[name]: value
});
};
handleSubmit = (event) => {
event.preventDefault();
console.log('提交的数据:', this.state);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="username"
value={this.state.username}
onChange={this.handleInputChange}
placeholder="用户名"
/>
<input
type="password"
name="password"
value={this.state.password}
onChange={this.handleInputChange}
placeholder="密码"
/>
<button type="submit">登录</button>
</form>
);
}
}
受控组件的特点:
- 数据完全由React管理
- 实时验证和处理用户输入
- 适合复杂的表单逻辑
四、非受控组件:让DOM自己玩
非受控组件则是让DOM自己管理数据,我们只是在需要的时候(比如提交时)去获取数据。
来看个例子:
javascript
class UncontrolledForm extends React.Component {
constructor(props) {
super(props);
this.usernameRef = React.createRef();
this.passwordRef = React.createRef();
}
handleSubmit = (event) => {
event.preventDefault();
const formData = {
username: this.usernameRef.current.value,
password: this.passwordRef.current.value
};
console.log('提交的数据:', formData);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
ref={this.usernameRef}
placeholder="用户名"
/>
<input
type="password"
ref={this.passwordRef}
placeholder="密码"
/>
<button type="submit">登录</button>
</form>
);
}
}
非受控组件的适用场景:
- 表单很简单,不需要实时验证
- 文件上传(
<input type="file">
) - 只是想简单获取用户输入,不需要复杂处理
五、三兄弟的对比总结
为了更直观,我做了个对比表格:
特性 | 高阶组件 | 受控组件 | 非受控组件 |
---|---|---|---|
用途 | 逻辑复用 | 表单控制 | 简单表单 |
数据管理 | 增强组件 | React State | DOM自身 |
实时响应 | 取决于实现 | 实时更新 | 提交时获取 |
代码量 | 较多 | 中等 | 较少 |
六、实际项目中的选择建议
根据我的经验:
- 用高阶组件当你需要在多个组件间共享逻辑时
- 用受控组件处理需要实时验证、复杂交互的表单
- 用非受控组件处理简单表单或者文件上传
有时候我也会混合使用:
javascript
// 混合使用示例
class HybridForm extends React.Component {
state = {
email: ''
};
fileRef = React.createRef();
handleEmailChange = (event) => {
this.setState({ email: event.target.value });
};
handleSubmit = (event) => {
event.preventDefault();
const formData = {
email: this.state.email,
resume: this.fileRef.current.files[0]
};
console.log('混合表单数据:', formData);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
{/* 受控组件 */}
<input
type="email"
value={this.state.email}
onChange={this.handleEmailChange}
placeholder="邮箱"
/>
{/* 非受控组件 */}
<input
type="file"
ref={this.fileRef}
/>
<button type="submit">提交</button>
</form>
);
}
}
七、最后的小贴士
- 高阶组件记得要传递props,避免"props丢失"问题
- 受控组件要注意性能,频繁的setState可能导致重渲染
- 非受控组件虽然简单,但失去了React的数据控制优势
理解这三个概念后,你在React开发中就能更加得心应手了。记住,没有绝对的好坏,只有适合的场景。
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!