React 的"组件即函数"理念是其设计哲学的核心,它将 UI 视为数据到视图的映射(UI = f(data)
),强调组件的纯粹性和不可变性。这种理念在函数组件(FC)和类组件(CC)的对比中体现得尤为明显:
1. 本质区别:函数 vs 类
-
函数组件(FC) :纯函数,输入
props
返回 JSX。jsxconst Greeting = (props) => <h1>Hello, {props.name}</h1>;
-
类组件(CC) :继承
React.Component
的类,需维护this
和生命周期。jsxclass Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
2. 状态管理:显式 vs 隐式
-
FC :通过
useState
/useReducer
显式管理状态,避免this
陷阱。jsxconst Counter = () => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>{count}</button>; };
-
CC :依赖
this.state
和this.setState
,状态逻辑分散在生命周期方法中。jsxclass Counter extends React.Component { state = { count: 0 }; increment = () => this.setState({ count: this.state.count + 1 }); render() { return <button onClick={this.increment}>{this.state.count}</button>; } }
3. 副作用处理:声明式 vs 命令式
-
FC :通过
useEffect
声明依赖关系,替代多个生命周期方法。jsxuseEffect(() => { document.title = `Count: ${count}`; // 副作用 return () => cleanup(); // 可选清理 }, [count]); // 依赖项数组
-
CC :需在
componentDidMount
、componentDidUpdate
和componentWillUnmount
中手动管理副作用。jsxcomponentDidMount() { document.title = `Count: ${this.state.count}`; } componentDidUpdate(prevProps, prevState) { if (prevState.count !== this.state.count) { document.title = `Count: ${this.state.count}`; } }
4. 生命周期:简化 vs 复杂
- FC :用
useEffect
统一处理挂载、更新和卸载,逻辑更集中。 - CC :需记忆多个生命周期方法(如
shouldComponentUpdate
、getDerivedStateFromProps
),易出错。
5. 不可变性:强制 vs 可选
- FC :函数式编程天然倾向不可变数据(如
[...arr, newItem]
),配合 Hooks 更安全。 - CC :可直接修改
this.state
(虽然不推荐),增加突变风险。
6. 测试与调试:简单 vs 繁琐
-
FC :纯函数易于单元测试,无
this
绑定问题。jsxexpect(Greeting({ name: 'Alice' })).toMatchSnapshot();
-
CC :需模拟
this
和生命周期,测试复杂。
7. 性能优化:更直观
-
FC :通过
React.memo
浅比较props
实现 shouldComponentUpdate,默认行为更可控。jsxconst MemoizedGreeting = React.memo(Greeting);
-
CC :需手动实现
shouldComponentUpdate
或继承PureComponent
。
总结:为什么"组件即函数"更好?
- 代码简洁 :消除样板代码(如
render
、this
)。 - 状态逻辑复用 :通过自定义 Hooks(如
useFetch
、useForm
)。 - 关注点分离 :
useEffect
明确副作用依赖,避免生命周期混乱。 - 类型安全:函数参数更易被 TypeScript 类型系统捕获。
- 未来趋势:React 团队推荐优先使用函数组件,新特性(如并发模式)更侧重 FC。
核心差异:函数组件通过纯函数和 Hooks 让组件逻辑更透明、可预测,而类组件依赖 OOP 继承模型,引入了更多抽象层和心智负担。