Компоненты React
React-компоненты — это базовые строительные блоки React-приложений. Компонент можно понимать как переиспользуемую, независимую единицу пользовательского интерфейса. Каждый компонент инкапсулирует собственную структуру, стили, логику и состояние.
React-компоненты — это краеугольный камень создания приложений. Компонент может быть таким же маленьким, как кнопка, или таким же большим, как целая страница.

Компоненты можно разделить на:Функциональные компонентыиКлассовые компоненты。
Технически React-компонент — это JavaScript-функция или класс, которые возвращают React-элемент (обычно JSX).
// 最简单的组件
function Hello() {
return <h1>Hello, World!</h1>;
}
Разбейте сложный интерфейс на дерево компонентов:
App ├── Header │ ├── Logo │ └── Navigation │ ├── NavItem │ └── NavItem ├── Main │ ├── Sidebar │ └── Content │ ├── Article │ └── Article └── Footer
Функциональные компоненты
Функциональные компоненты — это краткий способ определения компонентов.
Функциональный компонент — это JavaScript-функция, которая принимает props и возвращает React-элемент.
Базовый синтаксис:
// 方式 1:函数声明
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// 方式 2:箭头函数
const Welcome = (props) => {
return <h1>Hello, {props.name}</h1>;
};
// 方式 3:简化写法(单行返回)
const Welcome = (props) => <h1>Hello, {props.name}</h1>;
Создайте простой функциональный компонент:
Файл src/Welcome.js:
// Определяем функциональный компонент
function Welcome(props) {
return <h1>Привет, {props.name}!</h1>;
}
export default Welcome;
Отрендерите компонент в src/index.js:
Файл src/index.js:
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Отрендерите компонент Welcome и передайте проп name
root.render(<Welcome name="Мир" />);
Этот пример показывает простой компонент, который принимает проп name и отображает "Привет, Мир!" на странице.
Классовые компоненты
Классовые компоненты определяются с использованием синтаксиса классов ES6; обычно используются, когда вам нужно управлять состоянием или использовать методы жизненного цикла.
Базовый синтаксис:
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Создайте классовый компонент:
Пример
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Welcome;
Отрендерите компонент в src/index.js:
Пример
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Отрендерите компонент Welcome и передайте проп name
root.render(<Welcome name="Мир" />);
Пример теста
Далее мы создадим компонент, который выводит "Hello World!", с именем HelloMessage:
Пример React
Попробуйте »
Разбор примера:
1. Мы можем определить компонент с помощью функции:
function HelloMessage(props) {
return <h1>Hello World!</h1>;
}
Вы также можете использовать класс ES6 для определения компонента:
class Welcome extends React.Component {
render() {
return <h1>Hello World!</h1>;
}
}
2, const element = <HelloMessage />является пользовательским компонентом.
Обратите внимание, что имена нативных HTML-элементов начинаются со строчных букв, а имена пользовательских классов React — с заглавных. Например, HelloMessage нельзя записать как helloMessage. Кроме того, класс компонента может содержать только один тег верхнего уровня; иначе будет выдана ошибка.
If we need to pass parameters to a component, we can usethis.props, пример следующий:
Пример React
Попробуйте »
В приведённом выше примере,name— это свойство, которое получается черезprops.name.
Примечание: при добавлении атрибутов атрибут class нужно записывать как className, а атрибут for — как htmlFor. Это потому, что class и for — зарезервированные слова в JavaScript.
Составные компоненты
Мы можем объединить несколько компонентов в один компонент, то есть разделить различные функциональные аспекты компонента.
В следующем примере реализован компонент, который выводит название веб-сайта и URL:
Пример React
Попробуйте »
В примере компонент App использует компоненты Name, Url и Nickname для вывода соответствующей информации.
Пропсы (Свойства)
Пропсы — это способ передачи данных между компонентами, аналогично параметрам функции.
Базовое использование
// 父组件传递 props
function App() {
return (
<div>
<Greeting name="Alice" age={25} />
<Greeting name="Bob" age={30} />
</div>
);
}
// 子组件接收 props
function Greeting(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>Age: {props.age}</p>
</div>
);
}
Деструктуризация пропсов
// 推荐:直接解构
function Greeting({ name, age }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
</div>
);
}
// 带默认值的解构
function Button({ text = "Submit", variant = "primary", disabled = false }) {
return (
<button className={variant} disabled={disabled}>
{text}
</button>
);
}
Типы пропсов
Пропсы могут быть любым значением JavaScript:
function Demo() {
const user = { name: "Alice", age: 25 };
const numbers = [1, 2, 3, 4, 5];
const handleClick = () => alert("Clicked!");
return (
<MyComponent
// 字符串
title="Hello"
// 数字
count={42}
// 布尔值
isActive={true}
// 数组
items={numbers}
// 对象
user={user}
// 函数
onClick={handleClick}
// JSX
children={<p>This is content</p>}
/>
);
}
Дочерние пропсы
Специальные пропсы, используемые для передачи дочернего содержимого компонента:
// 方式 1:使用 props.children
function Card(props) {
return (
<div className="card">
<div className="card-body">
{props.children}
</div>
</div>
);
}
// 方式 2:解构 children
function Card({ children, title }) {
return (
<div className="card">
{title && <h2>{title}</h2>}
<div className="card-body">{children}</div>
</div>
);
}
// 使用
function App() {
return (
<Card title="My Card">
<p>This is the card content</p>
<button>Click me</button>
</Card>
);
}
Неизменяемость пропсов
Важный принцип: Никогда не изменяйте props!
// 错误:修改 props
function BadComponent(props) {
props.name = "Changed"; // 绝对不要这样做!
return <h1>{props.name}</h1>;
}
// 正确:将 props 视为只读
function GoodComponent({ name }) {
const displayName = name.toUpperCase(); // 创建新值
return <h1>{displayName}</h1>;
}
Композиция компонентов и повторное использование
Паттерн композиции
// 基础组件
function Avatar({ src, alt }) {
return <img src={src} alt={alt} className="avatar" />;
}
function UserInfo({ name, email }) {
return (
<div>
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
// 组合成复杂组件
function UserCard({ user }) {
return (
<div className="user-card">
<Avatar src={user.avatar} alt={user.name} />
<UserInfo name={user.name} email={user.email} />
</div>
);
}
Паттерн компонента-контейнера
// 容器组件:处理逻辑和状态
function Panel({ title, children, collapsible = false }) {
const [isOpen, setIsOpen] = useState(true);
return (
<div className="panel">
<div className="panel-header">
<h2>{title}</h2>
{collapsible && (
<button onClick={() => setIsOpen(!isOpen)}>
{isOpen ? "Collapse" : "Expand"}
</button>
)}
</div>
{isOpen && (
<div className="panel-content">
{children}
</div>
)}
</div>
);
}
// 使用
function App() {
return (
<Panel title="Settings" collapsible>
<p>Your settings here...</p>
</Panel>
);
}
Концепция компонента высшего порядка (реализуется через композицию)
// 通用的加载状态包装
function WithLoading({ isLoading, children }) {
if (isLoading) {
return <div>Loading...</div>;
}
return children;
}
// 使用
function UserList({ users, isLoading }) {
return (
<WithLoading isLoading={isLoading}>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</WithLoading>
);
}
Соглашения об именовании компонентов
Правила именования
// 正确:大写字母开头(PascalCase)
function UserProfile() { }
function BlogPost() { }
function NavBar() { }
// 错误:小写字母开头
function userProfile() { } // React 会将其视为 HTML 标签
Именование файлов
// 推荐的文件结构 src/ ├── components/ │ ├── Button.jsx // или Button.js │ ├── UserCard.jsx │ ├── Navigation/ │ │ ├── Navigation.jsx │ │ ├── NavItem.jsx │ │ └── index.js // 导出 Navigation
Экспорт и импорт компонентов
Экспорт по умолчанию
// Button.jsx
export default function Button({ text }) {
return <button>{text}</button>;
}
// App.jsx
import Button from './Button';
Именованный экспорт
// components.jsx
export function Button({ text }) {
return <button>{text}</button>;
}
export function Input({ value, onChange }) {
return <input value={value} onChange={onChange} />;
}
// App.jsx
import { Button, Input } from './components';
Смешанный экспорт
// Card.jsx
export default function Card({ children }) {
return <div className="card">{children}</div>;
}
export function CardHeader({ title }) {
return <div className="card-header">{title}</div>;
}
export function CardBody({ children }) {
return <div className="card-body">{children}</div>;
}
// App.jsx
import Card, { CardHeader, CardBody } from './Card';
Принципы проектирования компонентов
1. Принцип единственной ответственности
Каждый компонент должен делать что-то одно.
// 不好:组件做太多事情
function UserDashboard() {
// 获取用户数据
// 处理表单
// 显示图表
// 处理导航
// ...
}
// 好:拆分成多个组件
function UserDashboard() {
return (
<div>
<UserProfile />
<UserStats />
<UserActivity />
</div>
);
}
2. Держите компоненты простыми
Код компонента не должен превышать 200-300 строк.
// 好:提取子组件
function ProductCard({ product }) {
return (
<div className="product-card">
<ProductImage src={product.image} />
<ProductInfo name={product.name} price={product.price} />
<ProductActions productId={product.id} />
</div>
);
}
3. Разумно используйте props
Не передавайте слишком много props.
// 不好:props 过多
function User({ name, age, email, address, phone, company, role, ... }) { }
// 好:使用对象
function User({ user }) {
const { name, age, email } = user;
// ...
}
4. Избегайте глубокой вложенности
Чрезмерно глубокая вложенность компонентов может вызвать проблему проброса props.
// 问题:props 需要层层传递
<App>
<Layout user={user}>
<Sidebar user={user}>
<Menu user={user}>
<MenuItem user={user} />
</Menu>
</Sidebar>
</Layout>
</App>
// 解决:使用 Context 或状态管理
Другие расширения