六十天前端强化训练之第十五天React组件基础案例:创建函数式组件展示用户信息(第15-21天:前端框架(React))
=====欢迎来到编程星辰海的博客讲解======
我们已经学了14天了,再坚持坚持,马上我们就可以变得更优秀了,加油,我相信大家,接下来的几天,我会给大家更新前端框架(React),看完可以给一个免费的三连吗,谢谢大佬!
代码都可以在godepen上运行的,大家可以复制代码试试
https://codepen.io/accounts/signup/user/free/year?ownerId=null&ownerType=null
目录
一、组件核心概念体系
1.1 组件化开发哲学
1.2 虚拟DOM工作原理
二、函数式组件深度剖析
2.1 基础结构
2.2 Hooks 生态系统
三、组件通信模式详解
3.1 父→子通信(Props)
3.2 子→父通信(回调函数)
3.3 Context 跨层通信
实战案例:带交互的用户信息管理
功能演示
关键知识点总结
状态管理策略
列表渲染最佳实践
表单处理模式
性能优化手段
扩展学习路径
官方文档精读
社区优质资源
推荐工具链
进阶挑战任务
一、为删除操作添加确认对话框
二、实现用户编辑功能
三、添加本地存储持久化
四、集成后端API接口
五、添加分页加载功能
六、实现角色权限控制
功能演示
一、组件核心概念体系
1.1 组件化开发哲学
- 单一职责原则:每个组件应专注于单一功能
- 封装性:内部实现细节对外隐藏,通过 Props 接口通信
- 组合模式:通过组件嵌套形成树形结构
- 可重用性:合理抽象提升组件复用率
1.2 虚拟DOM工作原理
JAVASCRIPT
// 简化版虚拟DOM结构示例 const virtualNode = { type: 'div', props: { className: 'container', children: [ { type: 'h1', props: { children: 'Hello World' } }, { type: 'p', props: { children: 'React原理示例' } } ] } };
Diff 算法通过以下策略优化更新:
- 同级比较策略
- Key 值优化列表比对
- 组件类型判断(相同类型复用实例)
二、函数式组件深度剖析
2.1 基础结构
JSX
/** * 用户信息展示组件 * @param {Object} props - 组件属性 * @param {string} props.username - 用户名 * @param {number} props.age - 用户年龄 * @returns {JSX.Element} 用户信息卡片 */ function UserInfo({ username, age }) { return ( <div className="user-card"> <h2>{username}</h2> <p>年龄: {age} 岁</p> </div> ); }
2.2 Hooks 生态系统
JSX
import React, { useState, useEffect, useMemo } from 'react'; const UserDashboard = () => { // 状态管理:用户数据 const [users, setUsers] = useState([]); // 状态管理:加载状态 const [loading, setLoading] = useState(false); // 状态管理:错误信息 const [error, setError] = useState(null); // 计算属性:用户总数 const userCount = useMemo( () => users.filter(user => user.isActive).length, [users] ); // 副作用:数据获取 useEffect(() => { const fetchUsers = async () => { setLoading(true); try { const response = await fetch('/api/users'); if (!response.ok) throw new Error('数据获取失败'); const data = await response.json(); setUsers(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchUsers(); }, []); // 空依赖数组表示仅执行一次 // 条件渲染处理 if (loading) return <Spinner />; if (error) return <ErrorDisplay message={error} />; return ( <div> <h3>总用户数: {userCount}</h3> <div className="user-list"> {users.map(user => ( <UserCard key={user.id} {...user} /> ))} </div> </div> ); };
三、组件通信模式详解
3.1 父→子通信(Props)
JSX
// 父组件 const UserManagement = () => { const [userList, setUserList] = useState(initialUsers); const handleUserUpdate = (updatedUser) => { setUserList(prev => prev.map(user => user.id === updatedUser.id ? updatedUser : user ) ); }; return ( <div> <UserTable users={userList} onEdit={handleUserUpdate} /> </div> ); }; // 子组件 const UserTable = ({ users, onEdit }) => ( <table> <thead> <tr> <th>姓名</th> <th>操作</th> </tr> </thead> <tbody> {users.map(user => ( <tr key={user.id}> <td>{user.name}</td> <td> <button onClick={() => onEdit(user)}> 编辑 </button> </td> </tr> ))} </tbody> </table> );
3.2 子→父通信(回调函数)
JSX
const SearchBar = ({ onSearch }) => { const [query, setQuery] = useState(''); const handleSubmit = (e) => { e.preventDefault(); onSearch(query.trim()); }; return ( <form onSubmit={handleSubmit}> <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="输入搜索关键词..." /> <button type="submit">搜索</button> </form> ); }; // 父组件使用 <SearchBar onSearch={(keyword) => filterData(keyword)} />
3.3 Context 跨层通信
JSX
// 创建 Context const ThemeContext = React.createContext('light'); // 提供者组件 const App = () => { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Toolbar /> </ThemeContext.Provider> ); }; // 消费者组件 const ThemedButton = () => { const { theme, setTheme } = useContext(ThemeContext); return ( <button style={{ background: theme === 'dark' ? '#333' : '#fff', color: theme === 'dark' ? '#fff' : '#333' }} onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} > 切换主题 </button> ); };
实战案例:带交互的用户信息管理
JSX
import React, { useState, useEffect } from 'react'; /** * 用户信息管理系统 * 功能: * 1. 展示用户列表 * 2. 支持新增用户 * 3. 支持删除用户 * 4. 实时搜索过滤 */ const UserManager = () => { // 主数据状态 const [users, setUsers] = useState([]); // 搜索关键词状态 const [searchTerm, setSearchTerm] = useState(''); // 新用户表单状态 const [newUser, setNewUser] = useState({ name: '', email: '', role: 'user' }); // 模拟初始化数据 useEffect(() => { const initialUsers = [ { id: 1, name: '张三', email: 'zhang@example.com', role: 'admin' }, { id: 2, name: '李四', email: 'li@example.com', role: 'user' } ]; setUsers(initialUsers); }, []); // 处理表单输入 const handleInputChange = (e) => { const { name, value } = e.target; setNewUser(prev => ({ ...prev, [name]: value })); }; // 提交新用户 const handleAddUser = (e) => { e.preventDefault(); if (!newUser.name || !newUser.email) return; const userToAdd = { ...newUser, id: Date.now() // 临时ID生成方式 }; setUsers(prev => [...prev, userToAdd]); setNewUser({ name: '', email: '', role: 'user' }); }; // 删除用户 const handleDelete = (userId) => { setUsers(prev => prev.filter(user => user.id !== userId)); }; // 过滤用户列表 const filteredUsers = users.filter(user => user.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( <div className="user-manager"> {/* 搜索栏 */} <div className="search-section"> <input type="text" placeholder="搜索用户..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> </div> {/* 添加用户表单 */} <form onSubmit={handleAddUser} className="add-form"> <input name="name" placeholder="姓名" value={newUser.name} onChange={handleInputChange} required /> <input name="email" type="email" placeholder="邮箱" value={newUser.email} onChange={handleInputChange} required /> <select name="role" value={newUser.role} onChange={handleInputChange} > <option value="user">普通用户</option> <option value="admin">管理员</option> </select> <button type="submit">添加用户</button> </form> {/* 用户列表 */} <div className="user-list"> {filteredUsers.map(user => ( <div key={user.id} className="user-card"> <div className="user-info"> <h3>{user.name}</h3> <p>{user.email}</p> <span className={`role-tag ${user.role}`}> {user.role === 'admin' ? '管理员' : '用户'} </span> </div> <button className="delete-btn" onClick={() => handleDelete(user.id)} > 删除 </button> </div> ))} </div> </div> ); }; export default UserManager;
功能演示
- 实时搜索用户
- 添加新用户表单验证
- 用户角色标识
- 删除确认操作
- 响应式布局
关键知识点总结
-
状态管理策略
- 使用
useState
管理组件内部状态 - 状态提升:将共享状态移动到最近的共同祖先组件
- 状态合并:使用扩展运算符保持状态不变性
- 使用
-
列表渲染最佳实践
- 始终提供稳定的
key
属性 - 复杂列表使用虚拟滚动优化性能
- 分离列表项为独立子组件
- 始终提供稳定的
-
表单处理模式
- 受控组件 vs 非受控组件
- 表单验证实现方案
- 使用
name
属性批量处理输入
-
性能优化手段
React.memo
记忆组件useCallback
缓存函数引用useMemo
避免重复计算- 按需加载组件 (
React.lazy
)
-
错误边界处理
- 使用
try/catch
处理同步错误 - 异步操作的错误处理
- 全局错误边界组件
- 使用
扩展学习路径
-
官方文档精读
- 状态管理进阶
- Hooks 深度指南
- 上下文 API 最佳实践
-
社区优质资源
- React 模式大全
- Hooks 常见问题解答
- React 性能优化手册
-
推荐工具链
- 状态管理:Redux Toolkit / Recoil
- 路由管理:React Router v6
- 样式方案:Styled-components / CSS Modules
- 测试框架:Jest + React Testing Library
进阶挑战任务
- 为删除操作添加确认对话框
- 实现用户编辑功能
- 添加本地存储持久化
- 集成后端 API 接口
- 添加分页加载功能
- 实现角色权限控制
一、为删除操作添加确认对话框
JSX
const DeleteConfirmDialog = ({ onConfirm, onCancel }) => ( <div className="confirm-dialog"> <p>确定要删除该用户吗?</p> <div className="dialog-actions"> <button onClick={onConfirm}>确认删除</button> <button onClick={onCancel}>取消</button> </div> </div> ); // 使用示例 const handleDelete = (userId) => { const confirm = window.confirm('确定要删除该用户吗?'); if (confirm) { setUsers(prev => prev.filter(user => user.id !== userId)); } };
二、实现用户编辑功能
JSX
const UserEditor = ({ user, onSave, onCancel }) => { const [editData, setEditData] = useState(user); const handleSubmit = (e) => { e.preventDefault(); onSave(editData); }; return ( <div className="edit-form"> <form onSubmit={handleSubmit}> <input value={editData.name} onChange={(e) => setEditData({...editData, name: e.target.value})} /> <input value={editData.email} onChange={(e) => setEditData({...editData, email: e.target.value})} /> <div className="form-actions"> <button type="submit">保存</button> <button type="button" onClick={onCancel}>取消</button> </div> </form> </div> ); }; // 在用户卡片中添加: {isEditing ? ( <UserEditor user={user} onSave={(updated) => handleUpdateUser(updated)} onCancel={() => setEditingId(null)} /> ) : ( <button onClick={() => setEditingId(user.id)}>编辑</button> )}
三、添加本地存储持久化
JSX
// 自定义Hook const useLocalStorage = (key, initialValue) => { const [value, setValue] = useState(() => { const stored = localStorage.getItem(key); return stored ? JSON.parse(stored) : initialValue; }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }; // 使用示例 const [users, setUsers] = useLocalStorage('users', []);
四、集成后端API接口
JSX
const api = { fetchUsers: async (page = 1) => { const response = await fetch(`/api/users?page=${page}`); return response.json(); }, createUser: async (user) => { const response = await fetch('/api/users', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(user) }); return response.json(); } }; // 在组件中使用 useEffect(() => { const loadData = async () => { setLoading(true); try { const data = await api.fetchUsers(); setUsers(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; loadData(); }, []);
五、添加分页加载功能
JSX
const Pagination = ({ current, total, onChange }) => ( <div className="pagination"> {Array.from({length: total}, (_, i) => ( <button key={i+1} className={current === i+1 ? 'active' : ''} onClick={() => onChange(i+1)} > {i+1} </button> ))} </div> ); // 使用示例 const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); useEffect(() => { const loadPage = async () => { const { data, total } = await api.fetchUsers(currentPage); setUsers(data); setTotalPages(total); }; loadPage(); }, [currentPage]);
六、实现角色权限控制
JSX
// 创建权限上下文 const AuthContext = React.createContext(); const AuthProvider = ({ children }) => { const [currentUser, setCurrentUser] = useState({ role: 'admin' // 从登录获取实际值 }); const hasPermission = (requiredRole) => { return currentUser.role === requiredRole; }; return ( <AuthContext.Provider value={{ hasPermission }}> {children} </AuthContext.Provider> ); }; // 在组件中使用 const { hasPermission } = useContext(AuthContext); {hasPermission('admin') && ( <button onClick={handleEdit}>编辑</button> )}
功能演示
每个功能模块都可以独立实现并逐步集成,建议按以下顺序进行开发:
- 添加本地存储持久化
- 实现API集成
- 添加分页功能
- 实现编辑功能
- 添加权限控制
- 最后实现确认对话框
通过本案例可以完整掌握 React 核心组件的开发流程,建议结合实际项目需求扩展功能模块。