解决自动化脚本导出组件名与 HTML 保留字冲突
问题描述
组件库自动化脚本生成的入口文件中,组件名 header 和 menu 与 HTML 原生保留标签冲突,触发 ESLint 的 vue/no-reserved-component-names 规则报错。虽然运行时 Vue 优先使用注册的组件,但命名冲突违反了最佳实践。
问题复现
// 自动生成的 components.d.ts(冲突状态)
// ESLint 报错:'header' is a reserved HTML element name
app.component('header', _Header)
app.component('menu', _Menu)
typescript
解决方案
由于入口文件由脚本自动生成,需要修改自动化脚本而非手动调整生成产物。
脚本修改
// scripts/gen-components.ts
import path from 'node:path'
// HTML 保留标签名列表
const HTML_RESERVED = ['menu', 'header', 'footer', 'main', 'aside', 'nav', 'section']
// 遍历组件目录,生成导出和注册代码
function generateEntry(components: string[]) {
let exports = ''
let installs = ''
for (const filePath of components) {
const baseName = path.basename(filePath, path.extname(filePath))
// 判断是否为保留字,决定是否添加前缀
let componentName = baseName
if (HTML_RESERVED.includes(baseName)) {
componentName = `V${baseName.charAt(0).toUpperCase() + baseName.slice(1)}`
}
exports += `export { default as ${componentName} } from '${filePath}'\n`
installs += ` app.component('${componentName}', ${componentName})\n`
}
return { exports, installs }
}
typescript
优化写法
// 更简洁的变量命名
let componentName = baseName
if (HTML_RESERVED.includes(baseName)) {
componentName = `V${baseName}`
}
// 后续统一使用 componentName
typescript
执行脚本
pnpm run build:script:cgs
bash
生成结果验证
// 自动生成后(无冲突)
export { default as VHeader } from './header/index.vue'
export { default as VMenu } from './menu/index.vue'
export { default as Table } from './table/index.vue'
export default {
install(app: App) {
app.component('VHeader', VHeader)
app.component('VMenu', VMenu)
app.component('Table', Table)
},
}
typescript
通用前缀策略
借鉴 Element Plus 的 El 前缀规范,可为所有组件统一添加品牌前缀:
| 组件库 | 前缀 | 示例 |
|---|---|---|
| Element Plus | El | ElButton、ElTable |
| Ant Design Vue | A | AButton、ATable |
| Naive UI | N | NButton、NTable |
| 自研组件库 | Vp | VpButton、VpTable |
// 统一前缀方案
const PREFIX = 'Vp'
function withPrefix(name: string): string {
return `${PREFIX}${name.charAt(0).toUpperCase() + name.slice(1)}`
}
typescript
经验总结
- 组件命名与 HTML 保留字冲突是组件库开发中的常见问题
- 统一前缀既能避免冲突,又能提升组件库的品牌辨识度
- 修改自动化脚本(而非生成产物)确保重复构建结果一致
HTML_RESERVED列表应持续维护,覆盖所有可能的冲突场景
↑