AI 组件命名建议:命名不是美化,是降低维护成本
组件命名看起来是小事,但项目变大后,Card2、NewButton、UserPanelTemp 这类名字会让维护成本越来越高。AI 可以帮忙给组件命名,但不能只追求好听。命名要表达职责、范围和复用边界。
好的组件名,不是让人觉得高级,而是让后来的人一眼知道它该放在哪里、能不能复用。
一、先区分组件类型
flowchart TD
A[Component] –> B[Primitive]
A –> C[Composite]
A –> D[Feature]
A –> E[Page]
基础组件、组合组件、业务组件、页面组件,命名规则不应该一样。Button 可以很通用,InvoiceStatusCard 就应该带业务语义。
这四种类型的命名规则需要明确定义。基础组件是 UI 原子,命名应该描述视觉或交互功能:Button、Input、Modal、Tooltip、Spinner。它们通常存在于公共组件库中,不包含业务概念。
组合组件是用基础组件拼出来的可复用模块。比如 SearchBar = Input + Button + Dropdown。这类组件命名要表达组合功能:DateRangePicker、FileUploader、PaginationBar。它们也应该是无业务域的。
业务组件是最容易命坏的类型。它们承载了具体的业务语义,命名必须包含领域信息。比如发票模块的状态卡片应该叫 InvoiceStatusCard,而不是 StatusCard 或 InfoPanel。
页面组件就是路由入口,通常以 Page 结尾:SettingsPage、DashboardPage。
我们团队在 Code Review 时经常问一个简单问题:通过组件名和目录,你能判断这个组件能不能用在另一个业务模块吗?如果答案是不确定,命名就有问题。例如 OrderInfo 如果放在 shared/components 下,应该是一个通用订单信息组件,任何模块都可以用;但如果它里面引用了 orderService.createRefund,那它就不该在 shared 目录,名字也不能叫通用的 OrderInfo,应该叫 RefundActionPanel 并放在 features/refund/components 下。
二、让 AI 基于职责命名
给模型输入组件 props、使用场景和目录位置,而不是只给截图。
component_context:
props: [status, amount, dueDate, onPay]
domain: billing
usage: "dashboard payment reminder"
reusable: false
这种上下文下,PaymentReminderCard 比 InfoCard 更有维护价值。
提供上下文的粒度决定了 AI 命名建议的质量。除了 props 和 domain,建议再补充:
component_context_extended:
props: [status, amount, dueDate, onPay]
domain: billing
usage: "dashboard payment reminder"
directory: "features/billing/components"
data_dependencies: ["/api/billing/due-invoices"]
similar_components_in_project: ["ExpiredPlanAlert"]
similar_components_in_project 尤其重要。如果项目中已经有了 ExpiredPlanAlert,AI 可以参考命名风格,避免创建不一致的名字。同时告诉 AI 这个组件和已有组件的关系是并列还是替代,这会影响名字选择。
我们内部做了一个小工具,扫描组件文件提取 props 接口、import 语句和导出类型,自动生成上下文 JSON,然后喂给 AI。AI 输出三个命名候选加理由:
interface NamingInput {
filePath: string;
props: PropMeta[];
dependencies: string[];
domainHint?: string;
}
interface NamingSuggestion {
generic: string; // e.g. StatusCard
domain: string; // e.g. InvoiceStatusCard
page: string; // e.g. BillingOverviewStatusCard
reasoning: string;
}
开发者选一个,工具自动重命名文件并更新所有引用。这个流程比"想一个名字 -> 改文件 -> 手动更新引用"高效得多。
三、命名要配合目录结构
如果组件在 features/billing/components 下,名字可以少一点领域前缀;如果在公共组件库里,就必须更通用。
src/
components/Button.tsx
features/billing/components/PaymentReminderCard.tsx
pages/settings/SettingsPage.tsx
AI 命名建议最好同时给出放置目录。名称和目录一起看,才知道边界是否合理。
目录和命名的关系像"契约双签"。名字表达了组件的职责,目录表达了组件的归属。两者一致时,边界自然清楚。
我们的项目规范里有一条:
组件名包含领域信息(如 Payment) → 目录必须是 features/{domain}/components
组件名不含领域信息(如 Button、Modal) → 目录必须是 shared/components
组件名和目录不一致 → Code Review 必须被提问
这条规则可以人工检查,也可以通过 ESLint 自定义规则检查。例如一条规则:从 shared/components 目录导出的组件,文件名不能包含业务领域关键词(如 Order、Payment、Invoice)。这种简单规则能防止大多数边界混淆。
// ESLint 自定义规则示例
const SHARED_DIR = "shared/components/";
const DOMAIN_KEYWORDS = ["Order", "Payment", "Invoice", "User", "Billing"];
module.exports = {
create(context) {
const filename = context.getFilename();
if (!filename.includes(SHARED_DIR)) return {};
const nameMatch = filename.match(/([A-Z][a-zA-Z]+)\\.tsx$/);
if (!nameMatch) return {};
const componentName = nameMatch[1];
if (DOMAIN_KEYWORDS.some(kw => componentName.includes(kw))) {
context.report({
loc: { line: 1, column: 0 },
message: `shared/components 下的组件不应包含业务关键词 "${componentName}"`,
});
}
return {};
},
};
四、避免临时词进入长期代码
New、Old、Temp、V2 这类词可以短期迁移用,但不适合长期存在。它们表达的是时间,不是职责。
bad_names:
NewUserCard
ButtonV2
TempModal
better:
UserSummaryCard
IconButton
ConfirmDeleteDialog
如果确实要迁移,应该有删除计划。否则 V2 会陪项目走很多年。
可以把 AI 命名建议接入代码评审,但只做提示,不做强制。比如发现 Temp、New、Common 这类模糊词时,提醒作者补充职责语义。
name_review_rule:
warn_words: [New, Old, Temp, Common, Wrapper]
require_domain_when_feature_component: true
规则不是为了挑刺,而是让团队在命名时多想一步:这个组件到底表达什么边界?
Wrapper 是一个特别常见但很糟的名字。一个组件叫 ChartWrapper,半年后可能包了三层 unrelated 逻辑:数据格式化、主题切换、loading 状态。改名叫 ChartWithLoadingAndTheme 也太啰嗦。更好的做法是拆成 ChartLoader(数据)+ ThemedChart(主题)+ 页面层拼装。Wrapper 通常暗示了职责过重的设计。
还有一个容易被忽略的词是 Common。CommonList、CommonCard、CommonModal 这个名字太宽泛,会导致组件的 props 无限膨胀来适配所有场景。如果发现 Common* 组件的 props 超过 10 个,几乎可以确定它承担了太多职责。拆成更聚焦的命名,虽然要多写几个组件,但每个都比一个大杂烩好维护。
五、总结
AI 可以辅助组件命名,但输入要包含职责、props、使用场景、复用范围和目录位置。命名要表达边界,不只是好听。
组件名是代码里的路标。路标清楚,团队维护大型前端项目会轻松很多。
AI 可以给出候选名和理由,最终仍由团队选择。命名一旦进入公共组件库,就会被长期依赖,谨慎一点完全值得。
一个实用做法是让 AI 同时输出三个候选名:偏通用、偏业务、偏页面上下文。评审时比较它们的复用范围,比直接拍一个名字更稳。
naming_candidates:
generic: StatusCard
domain: InvoiceStatusCard
page: BillingOverviewStatusCard
候选名之间的差异,其实就是组件边界的差异。
