React 是由 Facebook 开发的一个用于构建用户界面的 JavaScript 库。它以其组件化架构、虚拟 DOM 和声明式编程范式而闻名,是现代前端开发的重要工具之一。

1. React 框架简介

1.1 什么是 React?

React 是一个专注于构建用户界面的 JavaScript 库,特别适用于构建单页应用程序(SPA)。它的核心思想是将用户界面分解为可重用的组件,每个组件管理自己的状态。

1.2 React 的核心特性

  • 组件化:将 UI 分解为独立、可复用的组件
  • 虚拟 DOM:提高性能的关键技术
  • 单向数据流:数据从父组件流向子组件
  • JSX 语法:JavaScript 和 HTML 的完美结合
  • 声明式编程:描述 UI 应该是什么样子,而不是如何实现
1
2
3
4
// React 组件示例
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}

2. React 组件使用方式

2.1 函数组件

函数组件是最简单的定义组件的方式,它接收 props 作为参数并返回 JSX 元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 基础函数组件
function Button({ text, onClick }) {
return (
<button onClick={onClick} className="btn">
{text}
</button>
);
}

// 使用 Hooks 的函数组件
import { useState, useEffect } from 'react';

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

useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);

return (
<div>
<p>你点击了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>
点击我
</button>
</div>
);
}

2.2 类组件

类组件提供了更多的生命周期方法和状态管理功能(虽然现在推荐使用函数组件 + Hooks)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React, { Component } from 'react';

class ClassCounter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

componentDidMount() {
console.log('组件已挂载');
}

incrementCount = () => {
this.setState({ count: this.state.count + 1 });
}

render() {
return (
<div>
<p>计数:{this.state.count}</p>
<button onClick={this.incrementCount}>增加</button>
</div>
);
}
}

2.3 组件通信

父子组件通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 父组件
function Parent() {
const [message, setMessage] = useState('Hello from Parent');

const handleChildClick = (childData) => {
console.log('来自子组件的数据:', childData);
};

return (
<div>
<Child
message={message}
onChildClick={handleChildClick}
/>
</div>
);
}

// 子组件
function Child({ message, onChildClick }) {
return (
<div>
<p>{message}</p>
<button onClick={() => onChildClick('子组件数据')}>
向父组件发送数据
</button>
</div>
);
}

Context API 全局状态管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { createContext, useContext } from 'react';

// 创建 Context
const ThemeContext = createContext();

// Provider 组件
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');

return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}

// 使用 Context
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);

return (
<button
className={`btn btn-${theme}`}
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
切换主题
</button>
);
}

3. 页面渲染优先级

3.1 React 18 并发特性

React 18 引入了并发渲染,允许 React 中断、暂停和恢复渲染工作,以保持应用的响应性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { startTransition, useDeferredValue } from 'react';

function SearchResults({ query }) {
// 延迟更新,降低优先级
const deferredQuery = useDeferredValue(query);
const results = searchData(deferredQuery);

return (
<div>
{results.map(result => (
<SearchItem key={result.id} item={result} />
))}
</div>
);
}

function SearchApp() {
const [query, setQuery] = useState('');

const handleInputChange = (e) => {
const value = e.target.value;

// 高优先级:立即更新输入框
setQuery(value);

// 低优先级:延迟更新搜索结果
startTransition(() => {
// 这里的更新会被标记为低优先级
performSearch(value);
});
};

return (
<div>
<input onChange={handleInputChange} value={query} />
<SearchResults query={query} />
</div>
);
}

3.2 性能优化策略

React.memo 避免不必要的重渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { memo } from 'react';

const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
console.log('ExpensiveComponent 渲染');

return (
<div>
{data.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}, (prevProps, nextProps) => {
// 自定义比较函数
return prevProps.data.length === nextProps.data.length;
});

useMemo 和 useCallback 优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { useMemo, useCallback } from 'react';

function OptimizedComponent({ items, category }) {
// 缓存计算结果
const filteredItems = useMemo(() => {
return items.filter(item => item.category === category);
}, [items, category]);

// 缓存函数引用
const handleItemClick = useCallback((id) => {
console.log('Item clicked:', id);
}, []);

return (
<div>
{filteredItems.map(item => (
<Item
key={item.id}
item={item}
onClick={handleItemClick}
/>
))}
</div>
);
}

4. 页面布局方式

4.1 CSS-in-JS 样式方案

Styled Components

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import styled from 'styled-components';

const Container = styled.div`
max-width: 1200px;
margin: 0 auto;
padding: 20px;
`;

const Header = styled.header`
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 8px;
`;

const GridLayout = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
`;

function LayoutExample() {
return (
<Container>
<Header>
<h1>我的应用</h1>
</Header>
<GridLayout>
<Card>卡片 1</Card>
<Card>卡片 2</Card>
<Card>卡片 3</Card>
</GridLayout>
</Container>
);
}

CSS Modules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// styles.module.css
.container {
max-width: 1200px;
margin: 0 auto;
}

.flexLayout {
display: flex;
justify-content: space-between;
align-items: center;
}

// Component.jsx
import styles from './styles.module.css';

function FlexLayoutComponent() {
return (
<div className={styles.container}>
<div className={styles.flexLayout}>
<div>左侧内容</div>
<div>右侧内容</div>
</div>
</div>
);
}

4.2 响应式布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { useState, useEffect } from 'react';

// 自定义 Hook 检测屏幕尺寸
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: undefined,
height: undefined,
});

useEffect(() => {
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}

window.addEventListener("resize", handleResize);
handleResize();

return () => window.removeEventListener("resize", handleResize);
}, []);

return windowSize;
}

function ResponsiveLayout() {
const { width } = useWindowSize();
const isMobile = width < 768;

return (
<div style={{
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
gap: '20px'
}}>
<aside style={{
width: isMobile ? '100%' : '250px',
background: '#f5f5f5',
padding: '20px'
}}>
侧边栏
</aside>
<main style={{
flex: 1,
padding: '20px'
}}>
主要内容区域
</main>
</div>
);
}

5. 布局调整方式

5.1 动态样式控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import { useState } from 'react';

function DynamicLayoutComponent() {
const [layout, setLayout] = useState('grid');
const [theme, setTheme] = useState('light');

const containerStyles = {
padding: '20px',
backgroundColor: theme === 'light' ? '#ffffff' : '#333333',
color: theme === 'light' ? '#333333' : '#ffffff',
transition: 'all 0.3s ease'
};

const layoutStyles = {
grid: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '20px'
},
flex: {
display: 'flex',
flexWrap: 'wrap',
gap: '20px'
},
list: {
display: 'flex',
flexDirection: 'column',
gap: '10px'
}
};

return (
<div style={containerStyles}>
<div style={{ marginBottom: '20px' }}>
<button onClick={() => setLayout('grid')}>网格布局</button>
<button onClick={() => setLayout('flex')}>弹性布局</button>
<button onClick={() => setLayout('list')}>列表布局</button>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
切换主题
</button>
</div>

<div style={layoutStyles[layout]}>
{[1, 2, 3, 4, 5, 6].map(item => (
<div key={item} style={{
padding: '20px',
background: theme === 'light' ? '#f0f0f0' : '#555555',
borderRadius: '8px'
}}>
项目 {item}
</div>
))}
</div>
</div>
);
}

5.2 CSS-in-JS 动画和过渡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import styled, { keyframes } from 'styled-components';

const fadeIn = keyframes`
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
`;

const AnimatedCard = styled.div`
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
animation: ${fadeIn} 0.5s ease-out;
transition: transform 0.2s ease;

&:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
}
`;

function AnimatedLayout() {
const [items, setItems] = useState([]);

const addItem = () => {
setItems([...items, { id: Date.now(), content: `项目 ${items.length + 1}` }]);
};

return (
<div>
<button onClick={addItem}>添加项目</button>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: '20px',
marginTop: '20px'
}}>
{items.map(item => (
<AnimatedCard key={item.id}>
{item.content}
</AnimatedCard>
))}
</div>
</div>
);
}

6. 实战案例:构建一个完整的布局系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { useState, createContext, useContext } from 'react';
import styled from 'styled-components';

// 布局配置 Context
const LayoutContext = createContext();

// 布局提供者组件
function LayoutProvider({ children }) {
const [config, setConfig] = useState({
sidebar: true,
theme: 'light',
layout: 'default'
});

return (
<LayoutContext.Provider value={{ config, setConfig }}>
{children}
</LayoutContext.Provider>
);
}

// 主布局组件
const AppContainer = styled.div`
min-height: 100vh;
background: ${props => props.theme === 'dark' ? '#1a1a1a' : '#ffffff'};
color: ${props => props.theme === 'dark' ? '#ffffff' : '#333333'};
transition: all 0.3s ease;
`;

const MainLayout = styled.div`
display: flex;
min-height: 100vh;
`;

const Sidebar = styled.aside`
width: ${props => props.collapsed ? '60px' : '250px'};
background: ${props => props.theme === 'dark' ? '#2d2d2d' : '#f8f9fa'};
transition: width 0.3s ease;
padding: 20px;
`;

const Content = styled.main`
flex: 1;
padding: 20px;
overflow-x: hidden;
`;

function CompleteLayoutSystem() {
const { config, setConfig } = useContext(LayoutContext);

const toggleSidebar = () => {
setConfig(prev => ({ ...prev, sidebar: !prev.sidebar }));
};

const toggleTheme = () => {
setConfig(prev => ({
...prev,
theme: prev.theme === 'light' ? 'dark' : 'light'
}));
};

return (
<AppContainer theme={config.theme}>
<MainLayout>
{config.sidebar && (
<Sidebar theme={config.theme}>
<h3>侧边栏</h3>
<nav>
<ul style={{ listStyle: 'none', padding: 0 }}>
<li style={{ marginBottom: '10px' }}>首页</li>
<li style={{ marginBottom: '10px' }}>文章</li>
<li style={{ marginBottom: '10px' }}>关于</li>
</ul>
</nav>
</Sidebar>
)}

<Content>
<header style={{ marginBottom: '20px' }}>
<button onClick={toggleSidebar}>
{config.sidebar ? '隐藏' : '显示'} 侧边栏
</button>
<button onClick={toggleTheme} style={{ marginLeft: '10px' }}>
切换到 {config.theme === 'light' ? '深色' : '浅色'} 主题
</button>
</header>

<section>
<h1>欢迎使用 React 布局系统</h1>
<p>这是一个完整的响应式布局示例,展示了如何使用 React 构建灵活的页面布局。</p>
</section>
</Content>
</MainLayout>
</AppContainer>
);
}

// 应用根组件
function App() {
return (
<LayoutProvider>
<CompleteLayoutSystem />
</LayoutProvider>
);
}

7. 总结

React 框架为现代前端开发提供了强大而灵活的解决方案。通过合理使用组件化架构、优化渲染性能、设计响应式布局,我们可以构建出高质量的用户界面。

关键要点

  1. 组件化思维:将 UI 分解为可重用的组件
  2. 性能优化:使用 memo、useMemo、useCallback 等优化手段
  3. 响应式设计:适配不同设备和屏幕尺寸
  4. 状态管理:合理使用 Context、Redux 等状态管理方案
  5. 现代特性:充分利用 React 18 的并发特性

掌握这些概念和技巧,你就能够使用 React 构建出现代化、高性能的 Web 应用程序!