claude-frontend-skill — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited claude-frontend-skill (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
这份规则描述的是在处理前端相关任务时的核心决策逻辑。前端开发的本质是状态与界面的同步问题,围绕这个本质展开的所有决策——组件如何划分、状态放在哪里、异步数据如何处理、性能如何保障——都有其内在的逻辑。理解这套逻辑能够让每一个前端决策都有坚实的依据,而不是靠直觉和习惯。
现代前端应用解决的核心问题是:如何在应用状态发生变化时,高效且正确地将界面更新到对应的状态。所有的框架(React、Vue、Angular)都是对这个问题的不同解答,但解决的是同一个问题。
理解了这个本质,就能理解为什么状态管理是前端最难的部分,为什么组件划分问题最终都是状态归属问题,为什么性能问题通常是状态变化触发了不必要的重新渲染。
前端应用中的状态可以分为四类,每类状态有不同的管理位置和策略。
服务器状态:从后端 API 获取的数据,比如用户列表、文章内容、订单记录。这类状态的特点是它的权威副本在服务端,前端持有的是一份缓存副本,需要处理加载、过期、重新获取、乐观更新等问题。
全局 UI 状态:在多个组件之间共享的界面状态,比如当前登录用户信息、主题设置、通知消息。这类状态需要在应用范围内共享,但与服务器数据无关。
局部 UI 状态:只属于某个组件及其子组件的状态,比如模态框是否打开、下拉菜单的展开状态、表单的校验状态。这类状态不需要跨组件共享。
表单状态:用户正在输入的值,包括输入内容、校验结果、提交状态。这类状态有其特殊的生命周期和处理模式。
flowchart TD
A[遇到需要管理的状态] --> B{状态的来源}
B -- 来自服务端 --> C[服务器状态\n使用专门的数据获取库管理]
B -- 多组件共享的 UI 状态 --> D[全局 UI 状态\n存放在全局状态管理器]
B -- 只属于单个组件树 --> E[局部 UI 状态\n存放在组件内部]
B -- 用户表单输入 --> F[表单状态\n使用表单管理方案]
C --> G[明确缓存策略和更新策略]
D --> H[明确谁可以修改这个状态]
E --> I[放在需要它的最低层级组件]
F --> J[明确校验时机和提交流程]当决定一个状态应该放在哪个组件时,原则是:放在能访问到这个状态的最低层级的共同祖先组件。
如果一个状态只被一个组件使用,放在这个组件内部。如果一个状态被兄弟组件共享,提升到它们的父组件。如果一个状态需要在应用的很多地方使用,放入全局状态管理器。
过早提升状态到全局会导致全局状态管理器变得臃肿,降低组件的可复用性;过晚提升会导致 props 通过多层组件传递,使得中间的组件与它们不需要的数据产生耦合。
组件划分不是按照 UI 的视觉区域来划分,而是按照状态和逻辑的归属来划分。一个组件应该是一个相对独立的状态和行为的封装单元。
实际的划分规则:如果一块 UI 有自己独立的状态(比如一个可展开折叠的面板),它应该是一个独立的组件。如果一块 UI 总是作为整体出现和消失,它可以是一个组件。如果一块 UI 在多个地方以相同的方式出现,它必须被提取为可复用的组件。如果一块 UI 的渲染逻辑已经复杂到难以理解,将它拆分为更小的组件。
一个组件对外暴露的 props 应该代表它的最小接口:完成这个组件的功能所必需的输入,不多也不少。
过多的 props 是组件职责不清晰的信号。如果一个组件需要十几个 props 才能正常工作,可能这个组件做了太多的事情,应该被拆分。
Props 的类型设计要体现业务含义,而不是技术类型。不要把业务对象拆散成多个基本类型的 props,这样会让组件与业务对象的结构产生多处绑定,一旦业务对象的结构变化需要修改多处。
flowchart TD
A[设计组件接口] --> B[识别组件完成其功能所需的最小信息]
B --> C{props 是否超过 5-7 个}
C -- 是 --> D[考虑拆分组件或合并相关 props 为对象]
C -- 否 --> E{props 是否暴露了实现细节}
E -- 是 --> F[重新设计为业务语义的 props]
E -- 否 --> G[props 设计合理]
D --> G
F --> G这个模式的核心是:负责获取数据和管理状态的组件,与负责渲染 UI 的组件分开。
容器组件负责:与外部数据源交互(API 调用、状态管理器)、管理复杂的业务逻辑、将数据和操作传递给展示组件。
展示组件负责:根据接收到的 props 渲染 UI、触发用户事件的回调、不包含业务逻辑和数据获取。
展示组件的价值在于:它们是可预测的(相同的 props 总是产生相同的输出)、可复用的(不依赖具体的数据源)、易于测试的(测试时只需要传入 props,不需要 mock 外部依赖)。
在前端处理任何异步操作时,必须处理四个状态:空闲、加载中、成功、失败。只处理成功状态是最常见的前端质量问题。
stateDiagram-v2
[*] --> 空闲 : 初始化
空闲 --> 加载中 : 触发操作
加载中 --> 成功 : 操作完成
加载中 --> 失败 : 操作出错
成功 --> 加载中 : 刷新数据
失败 --> 加载中 : 重试
成功 --> 空闲 : 重置
失败 --> 空闲 : 取消每个状态都需要对应的 UI 表现:空闲时展示初始状态或提示用户触发操作;加载中时展示加载指示器(骨架屏优于旋转图标,因为骨架屏减少了布局跳动);成功时展示数据;失败时展示有意义的错误信息和恢复操作(重试按钮)。
不是所有数据都应该在组件挂载时立即加载。加载策略的选择影响用户体验和性能。
立即加载:页面核心内容,用户看到页面就期望看到这部分数据。
按需加载:用户交互触发后才需要的数据,比如点击展开才显示的详情。
预加载:预测用户即将需要的数据,在用户实际触发操作前提前加载,减少等待时间。
无限滚动或分页:大量列表数据不应该一次性加载,应该在用户需要时逐步加载更多。
对于用户发起的写操作(点赞、删除、修改),可以采用乐观更新策略:在 API 请求发出后、响应返回前,就先在 UI 上更新状态,给用户即时的反馈。如果请求失败,再将 UI 状态回滚到操作前的状态,并告知用户操作失败。
乐观更新的适用条件:操作的成功率很高,失败回滚的视觉效果用户可以接受,操作的语义是幂等的。
前端性能优化不能靠直觉,因为直觉经常指向错误的地方。在优化之前,先测量:找出真正的性能瓶颈,然后针对瓶颈优化,验证优化后的改善。
不经测量的优化风险:优化了不是瓶颈的地方(浪费时间且可能引入 bug),引入了不必要的复杂性(memo、useMemo 本身有维护成本),过度优化使代码可读性下降但性能改善微乎其微。
不必要的重新渲染是现代前端框架中最常见的运行时性能问题。
导致不必要重新渲染的常见原因:在父组件的渲染函数中创建新的对象或函数作为 props(每次渲染都是新的引用,即使内容相同);全局状态中的某个部分更新触发了所有订阅了这个状态的组件重新渲染;列表渲染缺少稳定的 key 导致全量重新渲染。
flowchart TD
A[页面加载] --> B[加载关键资源\n首屏所需的 HTML CSS JS]
B --> C[渲染首屏内容\n用户看到有意义的内容]
C --> D[加载次要资源\n当前路由的完整功能]
D --> E[懒加载非关键资源\n图片 视频 非首屏内容]
E --> F[预取下一个可能的路由\n用户可能的下一步操作]用户的每一个操作都需要得到反馈,让用户知道操作是否被系统接受了。
即时反馈:按钮点击的视觉变化(在毫秒级),让用户知道操作被接受了。过程反馈:加载指示器,让用户知道系统正在处理(在秒级)。结果反馈:成功消息或错误消息,让用户知道操作的最终结果。
当操作失败时,用户需要知道三件事:发生了什么(错误的简明描述)、为什么失败(原因,如果可以提供的话)、怎么办(下一步的操作建议,比如重试、检查输入、联系支持)。
通用的"操作失败,请稍后重试"是最差的错误信息,因为它没有告诉用户任何有用的信息。
flowchart TD
A[用户填写表单] --> B[实时格式化输入]
B --> C[用户离开字段]
C --> D[字段级校验]
D --> E[显示或清除字段错误]
E --> F[用户点击提交]
F --> G[全量校验]
G --> H{所有字段是否有效}
H -- 否 --> I[显示所有错误\n聚焦到第一个错误字段]
H -- 是 --> J[禁用提交按钮]
J --> K[发送请求]
K -- 成功 --> L[清理表单状态\n跳转或显示成功消息]
K -- 失败,字段错误 --> M[将服务端错误显示在对应字段]
K -- 失败,系统错误 --> N[显示通用错误消息]
M & N --> O[恢复提交按钮]路由不仅仅是 URL 到页面的映射,它还承担着应用状态序列化的职责。用户应该能够通过 URL 分享和恢复任何应用状态,这意味着所有对用户有意义的状态都应该反映在 URL 中。
权限与路由的集成:路由守卫应该在渲染页面之前检查用户是否有权限访问,对于需要登录的页面,未认证用户应该被重定向到登录页,并在登录成功后重定向回原始目标 URL。
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.