为什么 AI 时代更需要配置化组件库
当 Cursor、Claude、Copilot 成为你的"结对编程"伙伴,你的组件库设计是在帮 AI,还是在为难 AI?
一个真实场景
产品经理走过来说:"做一个用户管理页面,有姓名、手机号、状态三个查询条件,表格展示数据,支持分页,能新增和编辑。"
你打开 AI 助手,输入这个需求。接下来发生的事,取决于你用的是什么组件库。
对比:传统模板写法 vs 配置化写法
传统 Element Plus 写法(AI 需要生成 ~120 行)
vue
<template>
<div class="user-page">
<!-- 查询表单 -->
<el-form :model="queryForm" inline>
<el-form-item label="姓名">
<el-input v-model="queryForm.name" placeholder="请输入姓名" clearable />
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="queryForm.phone" placeholder="请输入手机号" clearable />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="queryForm.status" placeholder="请选择" clearable>
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 工具栏 -->
<div class="toolbar">
<el-button type="primary" @click="handleAdd">新增</el-button>
</div>
<!-- 数据表格 -->
<el-table :data="tableData" v-loading="loading" border>
<el-table-column prop="name" label="姓名" />
<el-table-column prop="phone" label="手机号" />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="pagination.current"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="fetchData"
@size-change="fetchData"
/>
<!-- 新增/编辑弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" />
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="formData.phone" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="formData.status">
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const queryForm = reactive({ name: '', phone: '', status: '' })
const tableData = ref([])
const loading = ref(false)
const pagination = reactive({ current: 1, pageSize: 10, total: 0 })
const dialogVisible = ref(false)
const dialogTitle = ref('新增')
const formData = reactive({ name: '', phone: '', status: 1 })
const formRef = ref(null)
const rules = {
name: [{ required: true, message: '请输入姓名' }],
phone: [{ required: true, message: '请输入手机号' }]
}
async function fetchData() {
loading.value = true
try {
const res = await api.getUserList({
...queryForm,
pageIndex: pagination.current,
pageSize: pagination.pageSize
})
tableData.value = res.data
pagination.total = res.total
} finally {
loading.value = false
}
}
function handleQuery() { pagination.current = 1; fetchData() }
function handleReset() {
Object.assign(queryForm, { name: '', phone: '', status: '' })
handleQuery()
}
function handleAdd() { dialogTitle.value = '新增'; dialogVisible.value = true }
function handleEdit(row) {
dialogTitle.value = '编辑'
Object.assign(formData, row)
dialogVisible.value = true
}
function handleSubmit() {
formRef.value.validate(async (valid) => {
if (!valid) return
await api.saveUser(formData)
dialogVisible.value = false
fetchData()
})
}
function handleDelete(row) { /* ... */ }
fetchData()
</script>
问题在哪?
- AI 需要生成大量重复模板代码
- 每个
el-form-item+v-model都是潜在的拼写错误 - 事件绑定(
@click、@current-change、@size-change)容易遗漏 - 弹窗状态管理需要额外的
ref+v-model - 120+ 行代码 = 120 个出错机会
配置化写法(es-plus-ui,AI 只需生成 ~30 行)
vue
<template>
<es-table
ref="tableRef"
:columns="columns"
:options="options"
v-model:data-source="tableData"
v-model:pagination="pagination"
>
<es-form :model="queryForm" :form-item-list="queryItems" :config-btn="queryBtns" />
</es-table>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { useDialog } from 'es-plus-ui'
const queryForm = reactive({ name: '', phone: '', status: '' })
const tableData = ref([])
const tableRef = ref(null)
const pagination = ref({ current: 1, pageSize: 10, total: 0 })
const dialog = useDialog()
const queryItems = [
{ prop: 'name', label: '姓名', formtype: 'Input', span: 6 },
{ prop: 'phone', label: '手机号', formtype: 'Input', span: 6 },
{ prop: 'status', label: '状态', formtype: 'Select', span: 6,
dataOptions: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }
]
const queryBtns = [
{ name: '查询', type: 'primary', key: 'query', triggerEvent: true },
{ name: '重置', key: 'reset', triggerEvent: true },
{ name: '新增', type: 'primary', click: () => openForm('新增') }
]
const columns = [
{ prop: 'name', label: '姓名' },
{ prop: 'phone', label: '手机号' },
{ prop: 'status', label: '状态',
render: (_, { row }) => <ElTag type={row.status === 1 ? 'success' : 'danger'}>{row.status === 1 ? '启用' : '禁用'}</ElTag> },
{ prop: 'action', label: '操作', btns: [
{ name: '编辑', type: 'primary', clickEvent: (row) => openForm('编辑', row) },
{ name: '删除', type: 'danger', clickEvent: (row) => handleDelete(row) }
]}
]
const options = {
border: true,
httpRequest: (params) => api.getUserList(params),
configTableOut: { total: 'total', tableData: 'data', pageSize: 'pageSize', current: 'pageIndex' }
}
function openForm(title, row = {}) {
const formData = reactive({ name: '', phone: '', status: 1, ...row })
dialog({
title,
width: '500px',
render: (h, { registerRef }) => (
<EsForm ref={el => el && registerRef('form', el)} model={formData}
formItemList={[
{ prop: 'name', label: '姓名', formtype: 'Input', span: 24, formItemOptions: { rules: [{ required: true, message: '请输入姓名' }] } },
{ prop: 'phone', label: '手机号', formtype: 'Input', span: 24, formItemOptions: { rules: [{ required: true, message: '请输入手机号' }] } },
{ prop: 'status', label: '状态', formtype: 'Select', span: 24, dataOptions: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }
]}
/>
),
configBtn: [
{ name: '取消', click: (_, { close }) => close() },
{ name: '确定', type: 'primary', click: async (_, { close, getRefs }) => {
await getRefs('form')?.validate()
await api.saveUser(formData)
close()
tableRef.value?.httpRequestInstance()
}}
]
})
}
</script>
为什么 AI 更适合生成配置而不是模板?
1. Token 效率:相差 4 倍
| 指标 | 模板写法 | 配置化写法 |
|---|---|---|
| 代码行数 | ~120 行 | ~30 行 |
| Token 消耗 | ~800 tokens | ~200 tokens |
| AI 生成时间 | ~8 秒 | ~2 秒 |
| 出错概率 | 高(模板拼写、事件遗漏) | 低(纯数据结构) |
2. 结构化 = 可校验
配置化的本质是 JSON Schema 。AI 生成一个 { prop: 'name', label: '姓名', formtype: 'Input' } 对象,每个字段都有明确的类型约束。IDE 能提供自动补全,TypeScript 能在编译期发现错误。
而模板代码呢?v-modle 还是 v-model?@click 还是 @Click?这些拼写错误需要运行时才能发现。
3. 零胶水代码 = 零遗漏
传统写法中,查询按钮需要手动调 fetchData(),分页切换需要手动绑事件,重置需要手动清空每个字段------这些"胶水代码"AI 经常遗漏。
配置化写法中,triggerEvent: true 一个属性搞定一切。AI 不需要理解底层通信机制,只需知道"设为 true 就会自动查询"。
4. AI 理解意图,不需要理解实现
当你告诉 AI "添加一个手机号查询条件",对于配置化写法,AI 只需在数组中添加一项:
typescript
{ prop: 'phone', label: '手机号', formtype: 'Input', span: 6 }
对于模板写法,AI 需要:
- 在
<el-form>里加<el-form-item>+<el-input> - 确保
v-model绑定正确 - 确保
queryForm中有对应字段 - 确保
handleReset里也重置了这个字段
一步 vs 四步,错误率成倍增长。
AI Coding 时代的最佳实践
场景 1:自然语言 → CRUD 页面
markdown
你:帮我做一个订单管理页面
- 查询条件:订单号、客户名称、下单日期范围、订单状态
- 表格字段:订单号、客户名称、金额、状态、下单时间、操作
- 操作:查看详情、取消订单
- 状态用 Tag 展示不同颜色
AI 使用 es-plus-ui 可以一次性生成完整可用的页面,不需要反复修改模板错误。
场景 2:后端 API 变了,零代码适配
后端从 { result: { list: [], total: 100 } } 改成了 { data: { records: [], totalCount: 100 } }?
typescript
// 只改一行配置
configTableOut: { total: 'totalCount', tableData: 'records', pageSize: 'pageSize', current: 'pageIndex' }
不需要改任何业务代码。告诉 AI "后端响应格式变了",它只需修改这一个对象。
场景 3:批量生成
一个中后台项目通常有 20-50 个 CRUD 页面。使用配置化组件库:
- AI 生成每个页面只需 2 秒
- 所有页面风格一致
- 修改全局行为只需改一处全局配置
对比表:为什么配置化是 AI 的"母语"
| 维度 | 模板驱动 | 配置驱动 |
|---|---|---|
| AI 生成难度 | 高(需理解 Vue 模板语法、事件机制) | 低(只需生成 JSON 对象) |
| 出错率 | 高(拼写、遗漏、语法) | 低(结构化、可校验) |
| 修改成本 | 改模板+改逻辑+改状态 | 改一个字段 |
| 可复用性 | 低(每页重写) | 高(复用配置模式) |
| TypeScript 友好 | 一般(模板类型检查有限) | 强(完整类型推导) |
| 学习曲线 | AI 需要更多上下文 | AI 一次学会模式就能批量产出 |
不是"要不要用组件库",而是"用哪种范式"
AI 时代不会让组件库消亡------恰恰相反,它会让配置化组件库更有价值:
- AI 是最好的配置生成器 --- 人类讨厌写 JSON,但 AI 爱写
- 配置是最好的 AI 指令 --- 比自然语言精确,比代码简洁
- 配置化 = 确定性 --- 相同配置永远产出相同 UI,没有歧义
在 AI Coding 时代,组件库的设计标准应该从"人类写起来舒服"转变为"AI 生成起来准确、人类读起来清晰"。
这正是 es-plus-ui 的设计哲学:配置即界面,AI 即生产力。
快速体验
bash
npm install es-plus-ui element-plus @element-plus/icons-vue
typescript
import EsPlus from 'es-plus-ui'
import 'es-plus-ui/dist/style.css'
app.use(EsPlus)
- GitHub: github.com/liujiaao/es...
- 在线文档: liujiaao.github.io/es-plus
- npm: npmjs.com/package/es-...
如果这篇文章对你有帮助,欢迎 Star 支持!