🧩 组件库死亡倒计时?—— AI 编码冲击下的前端基础设施重构

🔍 引子:两个信号

最近我在一个开源项目里用 Cursor 辅助开发 UI,发现一个现象:AI 几乎总是首推 Shadcn/ui。

需要表格 → Shadcn Table + TanStack 需要弹窗 → 直接给你 Dialog 源码 需要日期选择 → 组合 Popover + Calendar

即使我没指定,它也倾向用 Shadcn 的源语来回答。

起初我有些抗拒。公司项目里 Element Plus 的庞大 API 早已是肌肉记忆。但有一次让 AI 给表格加行内编辑,两次体验彻底改变了我对"组件库"这件事的认知。


✨ 第一次惊讶:AI 突然变准了

场景 Element Plus Shadcn/ui
AI 怎么改组件 对着黑盒硬猜 直接修改源码文件
幻觉情况 编造不存在的方法:editRow()@row-dblclick 精准插入状态切换逻辑
类型推导 混用 onMounted / onUpdated 参数类型完全正确
根本原因 AI 只看到 API 外壳 AI 看到全部源码和状态流转

结论:对 AI 来说,源码是一等公民,API 文档只是二手信息。


🌪️ 第二次惊讶:样式开始漂移

几周后回顾整个项目,发现 UI 风格在悄悄分裂:

样式属性 开始前 几周后
圆角系统 统一 8px 8px、4px、直角随机组合
卡片内边距 统一 p-6 p-4p-5p-6 交错出现

AI 每次都直接改 Tailwind 类名来满足琐碎需求------改按钮颜色、调弹窗宽度、加 4px 行高。

Shadcn 把样式控制权完全交了出来,但没保留任何约束的护栏。自由带来了精准修改的能力,也带来了设计系统的碎片化。


🎯 一个深层矛盾 + 八个隐藏问题

这两次经验暴露了当前组件库范式的深层矛盾:

传统库用黑盒换稳定性,把 AI 挡在门外;Shadcn 用白盒换可修改性,却牺牲了一致性。

但问题不止于此。把"组件库"这个物种放到 AI 编码的聚光灯下审视,会发现更多失效点------这些不是某个库的缺陷,而是整个品类设计假设的崩塌


🥇 框架锁定:同一件事,N 套实现

现状 问题
React antdshadcnmui 各有 API,AI 记混
Vue element-plusnaive-ui 跟 React 完全不通用
Svelte 贫瘠的生态 自己造轮子

同一种行为模式(下拉菜单、弹窗、表格),被重复实现了 N 次,每次绑定一个框架。AI 切换上下文时准确率急剧下降。


🥈 版本锁定:版本是给人类的,不是给 AI 的

yaml 复制代码
Element Plus v1 → v2: 改了多少 API?没人记得清。
AI 的训练数据:混合了 v1 和 v2 的知识。
你的项目:装了 v2。
AI 写的代码:可能调的是 v1 的 API。

版本号把"规范的演进"和"实现的变更"绑在一起,AI 无法区分。


🥉 平台绑定:Web 会了,移动端从头学

行为:下拉选择 实现方式
Web div + 绝对定位 + 滚动列表
移动端 原生 Picker / Bottom Sheet
CLI stdin/stdout 选项列表

同一交互语义,三种实现,三套组件库。AI 要跨平台,先学三套 API。


📱 设备不感知

桌面端卡片有 hover,触屏不需要。桌面端表格展示 20 列,移动端只能展示 3 列。

组件不会告诉 AI"我在手机上应该长什么样"。AI 只能猜------桌面端对了,移动端大概率错。


📋 行为规范缺位

组件库暴露的是代码:export function Select(props)

不是行为规范:"按 ArrowDown 高亮下一个选项,按 Enter 选中,按 Escape 关闭。"

AI 能读代码,但它要的是设计意图------代码是"怎么做",AI 需要"做什么"和"为什么"。


🔍 隐式设计决策

为什么? 在哪记录的?
padding: 8px 设计评审决定的 某人的脑子里
color: #2563eb 品牌色 v3 Figma 注释里
radius: 4px vs 8px 等级区分 PR review 里

代码本身不携带"为什么"。AI 修改时只能外部推断,推断错了就引入不一致。


📄 文档和测试的重复劳动

一个组件:

复制代码
写代码 + 写文档 + 写 Storybook + 写测试 = 4 份离散工作

必须保持同步------但现实中从来不同步。如果 AI 已经生成了代码,它就具备了生成文档和测试所需的所有信息,但没人让它做。


♿ 无障碍是附加品,不是内建属性

每个组件库自己实现一次 ARIA。每个团队上线前再补一遍。AI 生成组件时,无障碍是最后才被想起的事。

如果规范本身就定义了"这个组件的 ARIA 角色是 menu",AI 一开始就能做对。


📊 全貌对比总结

维度 当前组件库 AI 需要什么
框架 绑定一个,切换重学 行为独立于框架,生成时适配
版本 版本号捆绑一切 版本绑定规范,不绑定实现
平台 Web 专属 一套规范,多平台生成
设备 桌面假设 设备差异显式声明
行为 代码即规范 规范独立于代码
决策 藏在讨论里 编码为可追溯的约束
文档/测试 手动维护,永远滞后 一次产出,多视图自动生成
无障碍 事后修补 规范内建,生成时保证

💡 代码越便宜,什么越贵?

AI 编码正在让代码的边际成本趋近于零。

写得快 ≠ 写得好。写得快 = 写得烂的速度也快。

当代码不再是稀缺资源,稀缺的东西变了:

越来越便宜 越来越贵
写一个组件 定义"什么是对的"
复制粘贴 维护一致性
堆功能 守住约束和边界
修 bug 保证正确性
写文档 保证文档跟代码一致

🏗️ 一个可能的架构:规范 → 生成

基于以上诊断,一个方向逐渐浮现:

把组件库从"代码包"重构为"规范描述器 + 生成引擎"

这不是"把组件拆成几层"(那是在旧框架里做优化),而是重新定义组件库的交付物

演进路线图

bash 复制代码
传统组件库 ──→ 源码级组件库 ──→ 规范驱动生成 ──→ 组件库消失
    │               │               │               │
    │  npm install  │ 源码复制      │ Spec 驱动    │ 意图驱动
    │  黑盒         │  白盒         │  约束 AI     │  AI 足够强
    │  AI 猜 API   │  样式漂移     │  规范=资产   │  不需要约束
    │               │               │               │
    Element Plus   Shadcn/ui      这个架构        未来?

架构示意图

typescript 复制代码
┌──────────────────────────────────────────────────────────────────┐
│                      🧠 规范层(Spec)                           │
│              唯一需要人工维护和版本化的东西                       │
│                                                                  │
│  ┌─────────────┐  ┌──────────┐  ┌──────────┐  ┌─────────────┐  │
│  │ 行为规范     │  │ 样式规范  │  │ 无障碍    │  │ 平台/设备   │  │
│  │ 状态定义     │  │ Token映射 │  │ ARIA角色  │  │ 适配规则    │  │
│  │ 事件流转     │  │ 约束规则  │  │ 键盘交互  │  │ 差异声明    │  │
│  └─────────────┘  └──────────┘  └──────────┘  └─────────────┘  │
└─────────────────────────┬────────────────────────────────────────┘
                          │ 读取
┌─────────────────────────▼────────────────────────────────────────┐
│                      ⚙️ 生成引擎(Generator)                    │
│                    AI 的工作,不是人的工作                        │
│                                                                  │
│  读取 Spec + 项目上下文                                           │
│       ↓                                                          │
│  ┌─────────────────────────────────────────────────────────┐     │
│  │  输出:                                                  │     │
│  │  📄 组件代码(.tsx / .vue / .svelte)                   │     │
│  │  📝 类型定义                                             │     │
│  │  🧪 测试用例                                             │     │
│  │  📖 文档 / Storybook                                    │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
│  切换平台/框架 = 换一个生成目标,Spec 不变                        │
└─────────────────────────┬────────────────────────────────────────┘
                          │ 检查
┌─────────────────────────▼────────────────────────────────────────┐
│                      🛡️ 约束层(Guardrails)                     │
│              确保 AI 的输出没有逾越边界                           │
│                                                                  │
│  ✅ 样式必须引用 token,禁止硬编码                               │
│  ✅ 无障碍要求必须满足,不通过不提交                             │
│  ✅ 代码必须通过项目 lint / type check                          │
│  ✅ AI 不得修改规范层文件                                        │
└──────────────────────────────────────────────────────────────────┘

这个架构解决了什么?

问题 ❌ 旧模式 ✅ 新架构
框架锁定 一个框架一套库 Spec 不变,生成引擎适配目标框架
版本锁定 升级库 = 全局风险 只有规范有版本,实现始终生成最新
平台绑定 Web/移动端/CLI 各三套 一套 Spec,三个生成目标
设备不感知 组件不知道自己在哪运行 Spec 中定义设备差异规则
行为规范缺位 代码里没有行为声明 Spec 第一层就是行为定义
隐式设计决策 藏在评审讨论里 Spec 明确记录设计约束
文档测试重复 四份离散工作各自同步 一次生成,四个输出视图
无障碍附加品 上线前补 Spec 内建,生成时自动包含

📝 伪代码:规范 vs. 实现

以下展示"规范"和"生成"之间的关系------这不再是传统组件库的样子。

这是"组件库"------一个规范文件,不是代码

typescript 复制代码
// 文件位置:@specs/dropdown-menu.ts
// 开发者维护此文件,AI 不可修改

export const dropdownMenuSpec = {
  id: 'dropdown-menu',
  version: '2.1',

  // ── 行为规范 ──
  states: {
    isOpen: { type: 'boolean', default: false },
    activeIndex: { type: 'number', default: -1 },
    selectedValue: { type: 'string | null', default: null },
  },

  transitions: [
    { trigger: 'trigger:click',         guard: '!isOpen', next: { isOpen: true } },
    { trigger: 'escape:keydown',        guard: 'isOpen',  next: { isOpen: false, activeIndex: -1 } },
    { trigger: 'arrowdown:keydown',     guard: 'isOpen',  next: { activeIndex: 'activeIndex + 1' } },
    { trigger: 'arrowup:keydown',       guard: 'isOpen',  next: { activeIndex: 'activeIndex - 1' } },
    { trigger: 'enter:keydown',         guard: 'isOpen',  next: { selectedValue: 'options[activeIndex]', isOpen: false } },
    { trigger: 'click-outside',         guard: 'isOpen',  next: { isOpen: false } },
  ],

  // ── 样式规范 ──
  styles: {
    container: {
      background: 'token.surface',
      borderRadius: 'token.radius.md',
      shadow: 'token.shadow.lg',
    },
    trigger: {
      height: 'token.size.input',
      padding: '0 token.spacing.md',
      border: '1px solid token.border.default',
    },
    option: {
      padding: 'token.spacing.sm token.spacing.md',
      states: {
        hover:    { background: 'token.color.primary-50' },
        selected: { background: 'token.color.primary', color: 'white' },
        disabled: { opacity: '0.5' },
      },
    },
  },

  // ── 无障碍规范 ──
  accessibility: {
    container: { role: 'menu', orientation: 'vertical' },
    trigger:   { role: 'combobox', ariaHasPopup: 'menu', ariaExpanded: 'isOpen' },
    option:    { role: 'option', ariaSelected: 'is selected' },
    keyboardNav: ['ArrowDown', 'ArrowUp', 'Enter', 'Escape', 'Home', 'End'],
    focusManagement: 'restore trigger on close',
  },

  // ── 平台适配规则 ──
  platform: {
    web:    { renderAs: 'div + absolute positioning' },
    mobile: { renderAs: 'bottom-sheet', keyboardNavInapplicable: true },
    cli:    { renderAs: 'stdin list', selectedIndicator: '→' },
  },

  // ── 约束(AI 不可违反) ──
  constraints: [
    '所有样式值必须引用 token,不得硬编码',
    'menu 关闭时必须将焦点归还 trigger',
    'option 数量超过 10 时启用虚拟滚动',
    '不得修改 spec 文件本身',
  ],
};

这是 AI 生成的组件------不是人写的

tsx 复制代码
// 目标框架:React 18 + Tailwind
// 生成自:dropdownMenuSpec

import { useDropdownMenu } from '@headless/dropdown-menu';
import { tokens } from '@/lib/tokens';
import { useClickOutside } from '@/hooks/useClickOutside';

export function DropdownMenu({ options, triggerLabel }: Props) {
  const { state, actions } = useDropdownMenu(dropdownMenuSpec);
  const ref = useRef<HTMLDivElement>(null);

  useClickOutside(ref, () => state.isOpen && actions.close());

  return (
    <div
      ref={ref}
      style={{
        background: tokens.surface,
        borderRadius: tokens.radius.md,
        boxShadow: tokens.shadow.lg,
      }}
      role="menu"
      aria-orientation="vertical"
    >
      <button
        onClick={actions.toggle}
        style={{
          height: tokens.size.input,
          padding: `0 ${tokens.spacing.md}`,
          border: `1px solid ${tokens.border.default}`,
        }}
        role="combobox"
        aria-haspopup="menu"
        aria-expanded={state.isOpen}
      >
        {state.selectedValue ?? triggerLabel}
      </button>

      {state.isOpen && (
        <div>
          {options.map((opt, i) => (
            <div
              key={opt.value}
              role="option"
              aria-selected={i === state.activeIndex}
              onClick={() => actions.select(opt.value)}
              style={{
                padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,
                ...(i === state.activeIndex && {
                  background: tokens.color.primary,
                  color: 'white',
                }),
              }}
            >
              {opt.label}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

两段代码的关系是:规范 → 生成,不是"组件库 → 复制修改"。


⚠️ 这还不是终局

这个架构有一个隐含前提:我们还不够信任 AI,所以需要用规范文件来约束它。

如果某天模型强大到读一遍项目就能理解你的设计语言、代码风格、业务语义------它能从历史代码中自动推导出规范,从 PR review 中学习设计决策------那规范层也会消失。

scss 复制代码
                        AI 能力
                           ▲
                           │
            没有组件库 ────┤────────────── ● (未来)
                           │
      规范驱动生成 ────────┤────── ● (这个架构)
                           │
      Shadcn 源码拷贝 ─────┤── ● (现在)
                           │
  Element Plus npm 包 ────┤ ● (过去)
                           └──────────────────────► 时间

届时,"组件库"这个物种将不复存在。UI 不再是组装出来的,而是根据意图即时生成的。

但那不是今天。


🎯 今天的实用问题

今天的实用问题是:在一份规范能约束 AI 的时候,我们应该怎么设计这份规范?

上面的架构不是答案,是一个锚点。用来讨论:

问题 你的看法?
规范应该写到什么粒度?
哪些东西必须被约束?
哪些应该交给 AI 自由发挥?
这套架构跟直接写代码比,是省了还是多了工作量?

你怎么看?

相关推荐
bryant_meng1 小时前
【Hugging Face】The GitHub of Open-Source AI Models
人工智能·github·qwen·hugging face·clip
有味道的男人1 小时前
从采集到铺货:AI 对接京东数据完整落地流程
人工智能
风止何安啊1 小时前
我一个前端仔,居然用 Python 搞起了 AI?从零到一,撸了个 AI 聊天框小 demo
前端·人工智能·后端
装不满的克莱因瓶1 小时前
图像尺寸调整:缩放矩阵如何改变像素坐标?
人工智能·线性代数·数学·算法·机器学习·矩阵
GlobalInfo1 小时前
八旋翼无人机产业洞察与市场占有率演变:2026年趋势分析报告
人工智能·无人机
GISer_Jing1 小时前
Claude Code插件系统全解析
前端·人工智能·ai·架构
AI前沿资讯1 小时前
2026年AI 3D赛道新势力崛起:一体化创作平台成主流,V2Fun凭全流程能力突围
人工智能·3d
猫头虎1 小时前
Cursor推出的Composer 2.5 是什么?从定向 RL 到合成数据,AI 编程智能体再进化
人工智能·开源·prompt·aigc·copilot·ai编程·composer
小茴香3531 小时前
Vue3路由权限动态管理
前端·前端框架·vue3