name: 前端基础 description: 回顾React/Vue组件架构、状态和钩子。在初级开发人员构建组件、表单、模态框、使用useState、useEffect、添加状态或询问“这是好的React吗?”时使用。
前端基础回顾
“一个组件应该做好一件事。如果你用‘并且’来描述它,就拆分它。”
何时应用
在以下情况激活此技能:
- React/Vue/Svelte组件
- UI渲染逻辑
- 状态管理代码
- CSS/样式决策
- 客户端路由
回顾清单
组件架构
- [ ] 单一职责:每个组件是否只做一件事?
- [ ] 大小检查:组件是否少于200行?
- [ ] 属性数量:属性是否少于7个?
- [ ] 命名:能否在不使用“并且”的情况下描述组件?
状态管理
- [ ] 就近原则:状态是否尽可能靠近其使用位置?
- [ ] 提升状态:状态是否通过父组件在兄弟组件之间正确共享?
- [ ] 上下文 vs 属性:是否避免了属性穿透(最多3层)?
- [ ] 服务器状态:服务器数据是否单独管理(如使用React Query/SWR)?
性能
- [ ] 记忆化:昂贵的计算是否用useMemo包裹?
- [ ] 回调函数:事件处理程序是否在需要时用useCallback包裹?
- [ ] 重新渲染:这会导致不必要的重新渲染吗?
- [ ] 懒加载:重型组件是否代码拆分?
可访问性
- [ ] 语义化HTML:是否使用适当的元素(如按钮而不是div)?
- [ ] ARIA:交互元素是否可访问?
- [ ] 键盘导航:用户能否不使用鼠标导航?
常见错误(反模式)
1. 上帝组件
❌ UserDashboard.tsx(1000行)
- 获取数据、管理状态、渲染UI、处理路由
✅ 拆分为:
- UserDashboardPage.tsx(容器)
- UserStats.tsx(展示)
- UserActivity.tsx(展示)
- useUserData.ts(钩子)
2. 逻辑在渲染中
❌ return <div>{users.filter(u => u.active).map(u => ...)}</div>
✅ const activeUsers = useMemo(() => users.filter(u => u.active), [users]);
return <div>{activeUsers.map(u => ...)}</div>
3. 属性穿透
❌ <App user={user}>
<Layout user={user}>
<Main user={user}>
<Widget user={user} />
✅ const user = useUser(); // 在Widget.tsx中
4. 布尔属性混乱
❌ <Button primary secondary large small disabled loading />
✅ <Button variant="primary" size="large" state="loading" />
苏格拉底式提问
向初级开发人员提问而不是直接给出答案:
- 架构:“这个组件的唯一职责是什么?”
- 拆分:“如果我要求你在其他地方只使用标题部分,你能做到吗?”
- 状态:“谁需要这个数据?它应该放在这里还是更高层?”
- 性能:“当父组件重新渲染时会发生什么?”
- 复杂度:“新开发者能在5分钟内理解这个吗?”
标准参考
详细模式见:
/standards/frontend/component-architecture.md
需要指出的红色标志
| 标志 | 提问问题 |
|---|---|
| 文件 > 200行 | “我们能将其拆分成更小的部分吗?” |
| > 5个useState调用 | “这些状态中的一些是否应该提升或合并?” |
| useEffect的依赖数组为空但使用外部值 | “我们是否缺少依赖项?” |
| 直接操作DOM | “是否有React的方式来做这个?” |
| 到处使用内联样式 | “我们是否应该使用一致的样式方法?” |