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
| 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> ); }
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';
const ThemeContext = createContext();
function ThemeProvider({ children }) { const [theme, setTheme] = useState('light');
return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); }
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
| .container { max-width: 1200px; margin: 0 auto; }
.flexLayout { display: flex; justify-content: space-between; align-items: center; }
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';
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';
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 框架为现代前端开发提供了强大而灵活的解决方案。通过合理使用组件化架构、优化渲染性能、设计响应式布局,我们可以构建出高质量的用户界面。
关键要点
- 组件化思维:将 UI 分解为可重用的组件
- 性能优化:使用 memo、useMemo、useCallback 等优化手段
- 响应式设计:适配不同设备和屏幕尺寸
- 状态管理:合理使用 Context、Redux 等状态管理方案
- 现代特性:充分利用 React 18 的并发特性
掌握这些概念和技巧,你就能够使用 React 构建出现代化、高性能的 Web 应用程序!