Appearance
组件库开发规范
适用于
apps/下所有@nexa/*组件库包。 组件库的目标消费者是products/tactics-sim-engine及未来的产品应用。
目录结构
每个组件库必须遵循以下结构:
apps/<package-name>/
├── package.json # name: @nexa/<name>, private: false
├── tsconfig.json # 引用 tsconfig.app.json + tsconfig.node.json
├── tsconfig.app.json # 库代码的 TS 配置
├── tsconfig.node.json # vite.config 的 TS 配置
├── vite.config.ts # 构建配置(library + app 双模式)
├── index.html # dev playground 入口
├── src/
│ ├── main.ts # dev playground 启动文件
│ ├── App.vue # dev playground 根组件(引入 src/lib 演示)
│ └── lib/ # 【库代码】对外发布的代码
│ ├── index.ts # 公共 API 入口(export * from)
│ ├── types.ts # 公共类型定义
│ ├── <Component>.vue # 主组件(PascalCase)
│ └── components/ # 内部子组件组件开发铁律
必须遵守
- 每个组件必须支持
embeddedprop:控制是否独立渲染标题栏。true时组件作为嵌入式面板,隐藏自有标题和关闭按钮,由宿主管理。 - 每个组件必须 emit
close事件:宿主可通过该事件响应关闭操作。 - 使用
<script setup lang="ts">:禁止 Options API。 - Props 使用 TypeScript 泛型:
defineProps<{ ... }>()。 - CSS Modules:推荐使用
<style module>避免样式污染宿主。如$style.panel、$style.header。 - 公共 API 从
src/lib/index.ts导出:组件、composable、类型定义均从此文件 re-export。
禁止事项
- ❌ 在组件中硬编码路由(组件库不拥有路由)
- ❌ 直接操作全局状态(不引入 Pinia store)
- ❌ 依赖特定的布局/容器结构
- ❌ 在库代码中引用
src/main.ts或src/App.vue(仅限 dev playground)
组件模式
主组件模板
vue
<script setup lang="ts">
import type { XxxProps } from './types'
const props = withDefaults(defineProps<XxxProps>(), {
embedded: false,
})
const emit = defineEmits<{
close: []
// 其他事件...
}>()
// 内部逻辑...
</script>
<template>
<div :class="[$style.panel, embedded && $style.embedded]">
<div v-if="!embedded" :class="$style.header">
<span :class="$style.title">面板标题</span>
<n-button quaternary @click="emit('close')">✕</n-button>
</div>
<div :class="$style.body">
<!-- 核心内容 -->
</div>
</div>
</template>
<style module>
.panel { /* 独立模式样式 */ }
.embedded { /* 嵌入模式样式(更紧凑) */ }
.header { display: flex; justify-content: space-between; align-items: center; }
.title { font-weight: 600; }
.body { flex: 1; overflow: auto; }
</style>Props 类型定义(types.ts)
typescript
export interface XxxProps {
/** 是否作为嵌入式面板(隐藏标题栏和关闭按钮),默认 false */
embedded?: boolean
// 其他 props...
}
export interface XxxEmits {
close: []
}依赖规则
- 内部依赖:通过
workspace:*引用@nexa/*包 - 外部框架:
vue、naive-ui、cesium必须声明为 peerDependencies - 构建工具:
vite、vite-plugin-cesium、vite-plugin-dts、vue-tsc放在 devDependencies
构建
build:lib:vite build --mode library→ 输出 ES + UMD 到dist/lib/build:vue-tsc -b && vite build --mode library→ 含类型检查的完整构建dev:vite→ 启动 dev playground(使用src/App.vue作为入口)- UMD 外部依赖必须配置
rollupOptions.output.globals,特别是@nexa/*内部依赖
验收标准
- [ ] 包名符合
@nexa/<name>规范 - [ ] 主组件支持
embeddedprop 和closeemit - [ ]
src/lib/index.ts正确导出所有公共 API - [ ] peerDependencies 声明完整(vue/naive-ui/cesium)
- [ ] devDependencies 不含运行时依赖
- [ ]
pnpm build:lib构建成功 - [ ] dev playground 可独立运行(
pnpm dev)