跳到主要内容

组件化

React 的组件化是其核心设计思想之一,通过将 UI 拆分为独立、可复用的组件,开发者可以更高效地维护、扩展和协作开发。

一、组件的核心概念

组件(Component)是 React 应用的基本构成单元,本质是一个可复用的 UI 片段,封装了自身的结构(HTML)、样式(CSS)和逻辑(JavaScript)。通过组合多个组件,可以构建复杂的整个应用界面。

1. 优点

  • 可复用性:一次编写,多处使用(如按钮、导航栏)
  • 可维护性:修改单个组件不影响其他部分
  • 可测试性:独立组件更容易编写单元测试
  • 协作友好:团队可并行开发不同组件
  • 逻辑清晰:组件化让代码结构更清晰,职责更分明,新人更容易理解项目结构

2. 设计原则

  • 单一职责:每个组件只负责一个功能
  • 高内聚,低耦合:组件内部的逻辑应当紧密相关(高内聚),而组件之间的依赖应该尽可能少(低耦合)
  • 可复用性优先:设计组件时,考虑其通用性。尽量让组件不依赖特定的业务逻辑,通过 props 来配置行为
  • 命名清晰:组件名应当清晰的反映其功能
  • 可组合性:通过组合小组件构成大组件,而非继承
  • 避免过度嵌套:虽然可以组合,但过深的组件嵌套会使的代码难以理解和调试。适时的将复杂的逻辑提取到可独立的组件或 Hook 中
  • Props 约束:明确 Props 的类型和默认值
  • 状态最小化:仅将必要的状态保留在组件内部,避免冗余
  • 性能意识:对高频更新的组件使用 React.memouseMemo 优化

二、组件的两种形式

React 支持两种形式的组件定义方式,目前 函数组件 + Hooks 是官方推荐的方案(React 16.8+)。

1.函数组件(Function Component)

用 JavaScript 函数定义,通过 return 返回 JSX(UI 结构)。

具有轻量、简洁的特定,依赖于 Hooks 管理状态和副作用。

// 使用函数式定义
function Title(props) {
return <h1>你好,{props.name}</h1>
}

// 使用箭头函数
const Title = (props) => <h1>你好,{props.name}</h1>

<Title name="Tom" /> // 渲染为 <h1>你好,Tom</h1>

2.类组件(Class Component)

用 ES6 类定义,需要继承 React.ComponentReact.PureComponent ,并通过 render() 方法返回 JSX。

是早期的主流方案,支持生命周期方法(如 componentDidMount),但代码量比较大。

class Title extends React.Component {
render() {
return <h1>你好,{this.props.name}</h1>;
}
}

3. 两种方式对比

  • 函数式组件
    • 更符合现代前端趋势
    • 配合 Hooks 可完全代替类组件的功能(状态、副作用、生命周期)
    • 代码更简洁
    • 性能通常更好
    • 当前 React 开发的首选和推荐模式
    • 没有 this 上下文问题(函数作用域),无需处理 this 绑定(事件回调无需手动 bind
  • 类组件
    • 需要注意 this 指向。类方法默认不绑定 this,若在事件回调中使用需要在构造函数手动绑定或使用箭头函数
    • 有完整的生命周期
    • 所有的状态集中在一个对象中,可能导致状态逻辑臃肿;复用逻辑需要通过高阶组件(HOC)或 Render Props ,增加了组件树的复杂度

三、组件的核心属性:Props 和 State

组件的行为通过由 外部输入(Props)内部状态(State) 共同驱动。

1. Props:父组件向子组件传递数据

Props 是组件的只读输入,用于接收父组件传递的数据(如配置、子节点等)。

  • 不可变:子组件无法直接修改 Props (单向数据流)
  • 类型检查:通过 prop-types 库或 TypeScript 约束类型

2. State(状态):组件内部管理的可变数据

State 是组件的私有属性,通过 setState (类组件)或 useState() (函数式组件)更新,会触发组件重新渲染。

  • 可变但受控:需通过特定的方法更新,直接修改值不会出发渲染
  • 异步更新setStateuseState 的更新是异步的(批量处理优化性能)
  • 合并更新setState 会合并新旧状态对象
import { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

const handleClick = () => {
setCount(count + 1);
// 或使用更新函数(避免闭包问题) setCount(prev => prev + 1)
};

return (
<div>
<p>点击次数:{count}</p>
<button onClick={handleClick}>+ 1</button>
</div>
);
}

四、 组件的组合和嵌套

React 鼓励 组合(Composition) 而非继承(Inheritance)来复用组件逻辑。通过嵌套组件,可以构建复杂的 UI 结构。

1. Children 属性:传递子节点

通过 props.children 可以接收父组件包裹的内容,实现类似“插槽”功能

function Wrapper(props) {
return <div className="wrapper">{props.children}</div>;
}
<Wrapper>
<h1>你好,Tom</h1>
<p>你看见 Jerry 了没有</p>
</Wrapper>;

2. 自定义属性:传递任意子节点或配置

除了 children 外,可通过自定义属性传递更加复杂的结构(如数组、对象)。

function Layout({ header, content, footer }) {
return (
<div>
<header>{header}</header>
<main>{content}</main>
<footer>{footer}</footer>
</div>
);
}

<Layout
header={<h1>你好,Tom<h1/>}
content={<p>Jerry 丢了</p>}
footer={<p>2025 年 10 月 29 日</p>}
/>