comp-hub 组件脚手架
基于 docs.comphub.cn 官方规范,快速生成符合 comp-hub 发布标准的业务组件。
组件目录结构
ComponentName/ # 组件名称 = 文件夹名(全局唯一)
├── index.vue # 入口文件(必需)
├── README.md # 组件文档(建议)
├── comp.json # 配置文件(自动生成,name + version + __id__)
├── main.js # UI 框架注册(可选,需要第三方 UI 库时添加)
├── demo/ # 预览示例
│ ├── index.vue # 小窗预览(列表页展示)
│ └── full.vue # 全屏预览(详情页展示,建议配置)
└── assets/ # 静态资源(如有)
核心规范(生成代码时必须遵守)
1. 命名规则
- 组件名称具有全局唯一性,不能与已有组件重名
- 建议采用前缀命名法:
公司名-业务域-组件名,如alipay-data-table - 仅支持字母、数字、连字符
-和下划线_
2. 资源引用 — 必须使用相对路径
✅ import bgIcon from './assets/bg.png'
❌ import bgIcon from '@/assets/bg.png'
3. 入口文件
- 必须包含
index.vue作为组件入口 - 组件应是自包含的,依赖通过 import 声明即可,系统会自动识别
4. UI 框架支持(可选 main.js)
组件预览基于 Vue 运行,所有 Vue 生态下的 UI 框架均可直接使用。只需在组件根目录添加 main.js 文件,引入并注册即可。
Vue 2
import Vue from 'vue';
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.use(Antd);
Vue 2 默认导出 Vue 构造函数,直接调用 Vue.use() 注册插件即可。
Vue 3
Vue 3 不再默认导出,所有导出都是具名导出。在 comp-hub 渲染环境下,组件预览的 app 实例由工具内部创建,main.js 无法通过 createApp() 创建 app。为此,comp-hub 会将内部 app 实例挂载到 Vue 命名空间上,直接通过 Vue.app 使用即可:
import * as Vue from 'vue';
import ArcoVue from '@arco-design/web-vue';
import '@arco-design/web-vue/dist/arco.css';
Vue.app.use(ArcoVue);
这与官方 app.use() 的调用方式不同,但功能等价——注册后,组件预览即可使用该 UI 框架的所有组件,无需在每个组件中重复导入。
5. Demo 文件
demo/mini.vue— 小窗预览,需固定内容尺寸(如 320×240)并使用缩放居中 API(见第 8 节)demo/full.vue— 全屏预览,展示完整功能,宽高继承父元素(width: 100%; height: 100%),无需缩放
6. 样式
- 支持 SCSS(
<style lang="scss" scoped>) - 支持 Less(
<style lang="less" scoped>) - 建议始终使用
scoped隔离样式
7. 第三方依赖
- 无需打包到组件中
- import 语句会被自动扫描提取
- 本地安装即可,用户预览时会根据依赖匹配规则自动适配
8. 缩放与居中 API(仅 mini 面板使用)
comp-hub 预览环境会为组件 Vue 实例注入两个方法,帮助 mini 面板的固定尺寸内容自适应预览面板大小。
重要:此 API 仅用于
demo/mini.vue(小窗预览)。demo/full.vue(全屏预览)不需要缩放,直接设置width: 100%; height: 100%继承父元素即可。
这些方法仅在 comp-hub 预览环境中存在,调用前务必做判空保护。
$getScaleStyle(params) — 主动查询缩放样式
同步获取基于内容尺寸与缩放模式计算出的缩放 + 居中样式。
type ScaleMode = "widthFirst" | "heightFirst" | "contain" | "cover"
interface ScaleStyle {
transform: string // 例如 "translate(100px, 50px) scale(0.75)"
transformOrigin: string // 固定为 "left top"
}
this.$getScaleStyle({
mode: ScaleMode // 缩放模式
width: number // 组件内容宽度(px)
height: number // 组件内容高度(px)
}): ScaleStyle
缩放模式说明:
| 模式 | 行为 |
|---|---|
| "widthFirst" | 按容器宽度缩放,高度可能溢出 |
| "heightFirst" | 按容器高度缩放,宽度可能溢出 |
| "contain" | 等比例缩放,内容始终完整可见(默认推荐) |
| "cover" | 等比例缩放,填满容器(可能裁切超出部分) |
所有模式均通过 translate 将内容居中于容器内。
Vue 2 Options API 示例(mini 面板):
<template>
<div :style="$getScaleStyle({ mode: 'contain', width: 320, height: 240 })">
<!-- 组件内容 -->
</div>
</template>
Vue 3 Composition API 示例(mini 面板):
import { getCurrentInstance } from "vue"
const instance = getCurrentInstance()
const scaleStyle = (instance?.proxy as any)?.$getScaleStyle?.({
mode: "contain",
width: 320,
height: 240
})
$onScaleChange(params, callback) — 订阅容器尺寸变化
注册时立即回调一次当前 scale,之后容器大小变化时自动回调最新值。返回取消订阅函数。
const unsubscribe = this.$onScaleChange(
params: { mode: ScaleMode, width: number, height: number },
callback: (style: ScaleStyle) => void
): () => void
Vue 2 Options API 示例(mini 面板):
<script>
export default {
data() {
return { scaleStyle: {} }
},
mounted() {
this._unsub = this.$onScaleChange(
{ mode: "contain", width: 320, height: 240 },
(style) => { this.scaleStyle = style }
)
},
beforeDestroy() {
this._unsub?.() // 取消订阅,防止内存泄漏
}
}
</script>
Vue 3 Composition API 示例(mini 面板):
<script setup>
import { ref, getCurrentInstance, onBeforeUnmount } from "vue"
const instance = getCurrentInstance()
const scaleStyle = ref({})
const unsub = (instance?.proxy as any)?.$onScaleChange?.(
{ mode: "contain", width: 320, height: 240 },
(style) => { scaleStyle.value = style }
)
onBeforeUnmount(() => unsub?.())
</script>
mini 面板完整示例(Vue 3 Composition API)
<template>
<div class="mini-wrapper" :style="scaleStyle">
<div class="mini-content">
<!-- 按 320×240 设计的内容 -->
...
</div>
</div>
</template>
<script setup>
import { ref, getCurrentInstance, onBeforeUnmount } from "vue"
const instance = getCurrentInstance()
const scaleStyle = ref({})
const unsub = (instance?.proxy as any)?.$onScaleChange?.(
{ mode: "contain", width: 320, height: 240 },
(style) => { scaleStyle.value = style }
)
onBeforeUnmount(() => unsub?.())
</script>
<style scoped>
.mini-wrapper {
transform-origin: left top;
}
.mini-content {
width: 320px;
height: 240px;
overflow: hidden;
}
</style>
full 面板示例(Vue 3,无需缩放)
<template>
<div class="full-content">
<!-- 完整功能展示,宽高继承父元素 -->
<MyComponent />
</div>
</template>
<style scoped>
.full-content {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
关键区别:mini 面板固定内容尺寸 + 缩放 API;full 面板直接
100%继承,不调用任何缩放 API。
最佳实践
- mini 面板用缩放,full 面板不缩放 — 分别参照上方两种模板编写
- 订阅优于轮询 — 使用
$onScaleChange响应容器变化,避免反复调用$getScaleStyle - 及时取消订阅 — 在
beforeDestroy/onBeforeUnmount中调用unsubscribe(),防止内存泄漏 - 预设固定尺寸 — mini 面板将内容设计为固定宽高(如 320×240),缩放交给 API
contain是默认安全选择 — 确保内容在小型预览面板中也完整可见- 判空保护非 comp-hub 环境 — 这些 API 仅在 comp-hub 预览中存在,调用前检查可用性:
// Vue 2 安全调用
if (this.$onScaleChange) {
this._unsub = this.$onScaleChange(
{ mode: "contain", width: 320, height: 240 },
(style) => { this.scaleStyle = style }
)
}
生成组件时的流程
- 确认组件名称(唯一,前缀命名法)
- 创建目录结构
- 生成
index.vue(入口组件) - 生成
demo/mini.vue(小窗预览,固定尺寸 + 缩放居中 API) - 生成
demo/full.vue或demo/full/index.vue(全屏预览,宽高100%继承父元素,不缩放。复杂组件可拆为多文件目录结构) - 生成
README.md(包含属性表、事件、使用示例、依赖说明、更新日志)—— 必须遵守标题命名规范(见下方)
6.1 README 标题命名规范
README.md 中的所有标题(以 # 开头的行)必须通过平台验证,否则组件上传失败。生成时严格遵守以下规则:
- 不能为空:标题必须有内容
- 不能以数字开头:禁止
### 1. xx、## 2.xx,应改为### xx、## xx - 禁止的字符:
#— 井号(会被解析为 Markdown 标题标记)`— 反引号(Markdown 代码标记)+、:、&、<、>、"、'、/、\、|、*、[、]、{、}、(、)、!、?、@、$、%、^、=、~、.、,、;- 换行符(
\n、\r)、制表符(\t)、换页符、垂直制表符
- 允许的特殊字符(仅以下 4 种):
- 连字符:
- - 下划线:
_ - 中文括号:
() - 空格
- 连字符:
正确示例:
## 基础搜索和分页
## 手动搜索(关闭自动查询)
## 分页自定义
## i18n 支持
## 分页参数名映射
错误示例:
## 1. 基础搜索 ← 禁止以数字开头
## 基础搜索 + 分页 ← 禁止 + 字符
## 手动搜索(autoQuery: false) ← 禁止英文括号 () 和冒号 :
## 读取 `col.value` ← 禁止反引号
## 什么是 BaseTable? ← 禁止 ?
标题中如需表达英文技术术语,可用中文替代或直接拼写为字母(如
i18n),不要使用特殊符号。
- 生成
comp.json({ "name": "...", "version": "1.0.0" },__id__由平台自动生成) - 如有第三方 UI 框架需求,生成
main.js
版本号规范
- 遵循语义化版本:
主版本.次版本.补丁版本 - 补丁版本:Bug 修复,向后兼容
- 次版本:新功能,向后兼容
- 主版本:破坏性变更
注意事项
- 重复组件会被平台检测,不会进入推荐/热门/最新列表
- 组件更新时只需修改代码 + 更新版本号,重新上传即可
- 平台保留所有历史版本,用户可切换查看和下载
- 依赖匹配默认使用"主版本"规则(主版本号相同即可)
- Vue 框架强制使用主版本匹配(Vue 2 ↔ Vue 3 不互通)
微信扫一扫