组件不再是唯一资产:生成式 AI 时代如何重构 UI 复用

2026-10-02 23 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

生成式 AI 正在改变 UI 复用的成本结构。过去,团队通过维护统一的组件包来避免重复开发;现在,只要设计系统足够清晰,模型就能按需生成大量标准界面。真正值得长期集中维护的资产,可能不再是每一个组件实现,而是设计令牌、交互规则、使用指南和自动化测试。

共享组件库的隐性成本正在变得更明显

一个中央组件包看起来能带来复用,但它也会持续产生维护费用:

  • 组件 API 需要兼容旧版本;
  • 每次调整都要发布、升级并处理依赖冲突;
  • 为了覆盖所有业务,组件往往积累大量布尔参数和条件分支;
  • 团队需要讨论哪些需求应该进入公共组件,哪些只能留在业务代码中;
  • 一个小的视觉改动,可能要等待组件库发版后才能落地。

当模型可以根据明确约束生成按钮、表单、卡片和布局时,复制实现代码的成本迅速下降。此时,继续把所有标准 UI 都包装成长期兼容的公共 API,未必是最经济的选择。

这并不意味着共享组件库应该被全部删除。日期选择器、数据表格、复杂弹窗、富文本编辑器以及经过严格无障碍验证的控件,仍然包含大量不适合反复生成的行为逻辑。变化主要发生在另一端:简单、样式驱动、容易验证的组件,可以从“必须复用的包”转变为“可以重新生成的本地代码”。

应该集中维护的是约束,而不只是实现

如果组件可以重新生成,设计系统就必须从展示文档升级为机器和开发者都能执行的契约。至少应集中管理四类内容:

  1. 设计令牌:颜色、间距、字体、圆角、阴影和动画时长。
  2. 语义与交互规则:何时使用主按钮、错误信息放在哪里、加载状态如何表达。
  3. 无障碍要求:键盘操作、焦点样式、语义标签和 ARIA 使用边界。
  4. 自动化验证:视觉回归、交互测试、令牌检查和无障碍扫描。

组件实现可以分散在业务仓库中,但这些约束必须保持中央化。否则,生成只会把手工复制粘贴造成的漂移,升级成速度更快的自动化漂移。

一种可行的资产分层方式是:

层级 是否中央维护 例子
设计令牌 是 颜色、间距、圆角、排版
UI 规则与生成提示 是 状态要求、无障碍规则、禁用模式
高复杂度基础控件 通常是 Combobox、DatePicker、DataGrid
标准展示组件 可按需生成 Card、Badge、简单 Button
业务组合组件 留在业务侧 CheckoutSummary、UserQuotaPanel

一个可执行的“生成后验证”示例

下面假设项目使用 React、普通 CSS 和 Node.js 18 或更高版本。示例并不依赖特定 AI API:可以让模型生成组件,但生成结果必须通过同一套设计契约检查。

先定义中央令牌文件 design-system/tokens.css:

:root {
  --color-action-bg: #2457d6;
  --color-action-bg-hover: #1946b3;
  --color-action-text: #ffffff;
  --color-focus-ring: #80a7ff;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --radius-md: 0.5rem;
}

生成的业务侧组件 src/Button.jsx 可以保持简单,并直接进入应用源码:

import './Button.css';

export function Button({ children, loading = false, disabled = false, ...props }) {
  return (
    <button
      className='button'
      disabled={disabled || loading}
      aria-busy={loading}
      {...props}
    >
      {loading ? 'Saving…' : children}
    </button>
  );
}

对应的 src/Button.css 只能使用批准的设计令牌:

.button {
  border: 0;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  color: var(--color-action-text);
  background: var(--color-action-bg);
  cursor: pointer;
}

.button:hover:not(:disabled) {
  background: var(--color-action-bg-hover);
}

.button:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

接着添加 scripts/check-ui-contract.mjs,检查组件是否引用了不存在的令牌,以及是否绕过令牌直接写入颜色值:

import { readFile } from 'node:fs/promises';

const tokenFile = 'design-system/tokens.css';
const componentFiles = ['src/Button.css'];

const tokens = await readFile(tokenFile, 'utf8');
const defined = new Set(
  [...tokens.matchAll(/(--[\w-]+)\s*:/g)].map((match) => match[1])
);

let failed = false;

for (const file of componentFiles) {
  const css = await readFile(file, 'utf8');
  const used = [...css.matchAll(/var\((--[\w-]+)/g)].map((match) => match[1]);
  const unknown = [...new Set(used.filter((name) => !defined.has(name)))];
  const rawColorMarkers = ['#', 'rgb(', 'rgba(', 'hsl(', 'hsla('];
  const containsRawColor = rawColorMarkers.some((marker) => css.includes(marker));

  if (unknown.length > 0) {
    console.error(`${file}: unknown tokens: ${unknown.join(', ')}`);
    failed = true;
  }

  if (containsRawColor) {
    console.error(`${file}: raw color found; use a design token instead`);
    failed = true;
  }
}

if (failed) {
  process.exitCode = 1;
} else {
  console.log('UI contract check passed');
}

在项目根目录运行:

node scripts/check-ui-contract.mjs

真实项目可以把 componentFiles 改为递归扫描,也可以继续加入间距、字体、动画和废弃令牌检查。这个脚本不是完整的设计系统验证器,但它展示了关键变化:团队不再要求所有页面导入同一个 Button 包,而是要求所有 Button 实现遵守同一份可执行契约。

生成组件时,也可以固定使用一段仓库内提示词:

Generate a local React component under src/components.

Source of truth:
- Use only CSS variables defined in design-system/tokens.css.
- Do not add runtime dependencies.
- Prefer semantic HTML over ARIA replacements.
- Include default, hover, focus-visible, disabled, and loading states.
- Keep business-specific props out of generic UI components.
- Add interaction tests for keyboard and disabled behavior.

Return the component, stylesheet, and tests as separate files.

提示词本身也应该像代码一样接受评审和版本管理。模型可以变化,但输入约束和验收门槛不能随意漂移。

不要把“可再生”误解成“无需治理”

按需生成会引入新的风险。不同模型或不同提示词可能产生结构不同但视觉相似的代码;同一个缺陷也可能被复制到多个业务仓库。生成速度越快,代码审查和自动化测试的重要性越高。

可以按以下标准决定是否保留中央组件:

  • 行为复杂度高:涉及焦点管理、浮层定位、异步状态或大量键盘交互时,优先共享成熟实现。
  • 错误代价高:支付、身份验证、隐私授权等场景不应依赖未经验证的即时生成。
  • 变化频率低但复用率高:稳定基础控件继续共享通常更便宜。
  • 样式简单且业务差异大:更适合基于令牌在业务侧生成。
  • 无法自动验证:在建立测试和检查规则之前,不要急于拆掉现有组件库。

迁移时先改变默认路径

团队不必一次性废弃现有组件包。更稳妥的做法是保留复杂基础控件,同时选择 Badge、Card、空状态和简单表单布局进行试点。

迁移检查清单可以很短:

  • 设计令牌是否有稳定名称和明确语义;
  • 使用指南能否被转换为具体生成约束;
  • CI 是否能发现视觉、交互和无障碍回归;
  • 生成代码是否直接归业务团队维护;
  • 高频重复模式是否会被重新提升为共享组件;
  • 模型升级后是否有固定样例用于回归评估。

生成式 AI 并没有消除复用,而是把复用的中心从“同一份组件代码”移向“同一套设计决策和质量门槛”。组件可以被重新生成,设计系统、规则和测试则必须比过去更可靠。


相关推荐