| name | create-component |
| description | 在 wot-ui 项目中创建新组件骨架与必要注册点。用户要求从零创建组件源码、补齐 types.vue.scss 结构或注册全局组件类型时调用;不负责 Demo 页、测试和文档迁移。 |
创建新组件技能
本技能用于在 wot-ui 项目中创建新的 UI 组件骨架。
默认遵循 wot-ui-component-baseline 中的共享约束,命名与注释细则可配合 vue-comment 使用。
职责边界
- 本 Skill 负责组件源码目录、基础文件、必要注册点。
- 本 Skill 不负责 Demo 页编写,相关工作交给
create-demo-page。
- 本 Skill 不负责测试创建,相关工作交给
create-test。
- 本 Skill 不负责 Markdown 文档迁移或大规模文档编写,相关工作交给
migrate-component-doc。
组件目录结构
每个组件位于 src/uni_modules/wot-ui/components/wd-{组件名}/ 目录下,包含以下文件:
wd-{组件名}/
├── types.ts # 类型定义文件
├── wd-{组件名}.vue # 组件主文件
└── index.scss # 样式文件
创建步骤
1. 创建组件目录
mkdir -p src/uni_modules/wot-ui/components/wd-{组件名}
2. 创建类型定义文件 (types.ts)
import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
import { baseProps, makeBooleanProp, makeNumberProp, makeNumericProp, makeStringProp } from '../common/props'
export type {组件名}Type = 'primary' | 'success' | 'warning' | 'danger'
export const {组件名驼峰}Props = {
...baseProps,
prop1: makeStringProp(''),
disabled: makeBooleanProp(false),
count: makeNumberProp(0),
value: makeNumericProp('')
}
export type {组件名}Props = ExtractPropTypes<typeof {组件名驼峰}Props>
export type {组件名}Expose = {
methodName: () => void
}
export type {组件名}Instance = ComponentPublicInstance<{组件名}Expose, {组件名}Props>
Props 工具函数说明
| 工具函数 | 用途 | 示例 |
|---|
makeStringProp(default) | 字符串属性 | makeStringProp('') |
makeBooleanProp(default) | 布尔属性 | makeBooleanProp(false) |
makeNumberProp(default) | 数字属性 | makeNumberProp(0) |
makeNumericProp(default) | 数字或字符串属性 | makeNumericProp('') |
makeArrayProp<T>() | 数组属性 | makeArrayProp<string>() |
makeRequiredProp(type) | 必填属性 | makeRequiredProp(String) |
3. 创建组件文件 (wd-{组件名}.vue)
<template>
<view :class="rootClass" :style="customStyle">
<!-- 组件内容 -->
<slot></slot>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-{组件名}',
options: {
addGlobalClass: true,
// #ifndef MP-TOUTIAO
virtualHost: true,
// #endif
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import { computed } from 'vue'
import { {组件名驼峰}Props, type {组件名}Expose } from './types'
const props = defineProps({组件名驼峰}Props)
// Emits 定义
const emit = defineEmits<{
click: [event: Event]
change: [value: string]
}>()
// 计算根节点类名
const rootClass = computed(() => {
return `wd-{组件名} ${props.customClass}`
})
// 组件方法
function handleClick(event: Event) {
emit('click', event)
}
// 暴露给父组件的方法
defineExpose<{组件名}Expose>({
methodName: () => {
// 实现
}
})
</script>
<style lang="scss">
@use './index.scss';
</style>
组件选项说明
addGlobalClass: true - 允许使用全局样式类
virtualHost: true - 开启虚拟节点模式
styleIsolation: 'shared' - 样式共享模式
4. 创建样式文件 (index.scss)
@use '../../styles/mixin/mixin.scss' as *;
@use '../../styles/variable.scss' as *;
${组件名}-bg: var(--wot-{组件名}-bg, $filled-oppo);
${组件名}-padding: var(--wot-{组件名}-padding, $padding-loose);
${组件名}-border-radius: var(--wot-{组件名}-border-radius, $radius-main);
@include b({组件名}) {
display: flex;
padding: ${组件名}-padding;
background: ${组件名}-bg;
border-radius: ${组件名}-border-radius;
@include e(header) {
}
@include e(content) {
}
@include e(footer) {
}
@include when(disabled) {
opacity: $opacity-disabled;
}
@include when(active) {
}
@include m(primary) {
}
@include m(large) {
}
}
BEM 命名规范
| Mixin | 生成选择器 | 说明 |
|---|
@include b(name) | .wd-name | 定义块 (Block) |
@include e(elem) | .wd-name__elem | 定义元素 (Element) |
@include m(mod) | .wd-name--mod | 定义修饰符 (Modifier) |
@include when(state) | .wd-name.is-state | 定义状态 |
@include edeep(elem) | :deep(.wd-name__elem) | 穿透子组件样式 |
@include me(elem) | 嵌套在 m 下的 e | 修饰符下的元素 |
常用样式变量
| 类别 | 变量示例 | 说明 |
|---|
| 颜色 | $primary-6, $danger-main, $text-main | 语义化颜色 |
| 间距 | $padding-loose, $spacing-tight | 内边距/间距 |
| 圆角 | $radius-main, $radius-large | 边框圆角 |
| 字体 | $typography-body-size-main | 字号 |
| 边框 | $border-main, $stroke-main | 边框 |
常用 Composables
项目提供了多个可复用的组合式函数:
| Composable | 用途 |
|---|
useParent | 获取父组件实例 |
useChildren | 管理子组件 |
useLockScroll | 锁定页面滚动 |
useClickAway | 点击外部区域检测 |
useQueue | Toast/Notify 队列管理 |
useTranslate | 国际化 |
使用示例:
import { useLockScroll } from '../composables/useLockScroll'
useLockScroll(() => showPopup.value)
条件编译
uni-app 支持跨平台条件编译:
<!-- 仅 H5 平台 -->
// #ifdef H5
<view>H5 专用内容</view>
// #endif
<!-- 仅微信小程序 -->
// #ifdef MP-WEIXIN
<view>微信小程序专用</view>
// #endif
<!-- 非 App 平台 -->
// #ifndef APP
<view>非 App 内容</view>
// #endif
5. 注册全局类型声明 (global.d.ts)
在 src/uni_modules/wot-ui/global.d.ts 中添加组件类型声明:
declare module 'vue' {
export interface GlobalComponents {
Wd{组件名帕斯卡}: typeof import('./components/wd-{组件名}/wd-{组件名}.vue')['default']
}
}
命名规则:组件名使用帕斯卡命名法(PascalCase),如 WdVideoPreview、WdIndexBar
交付要求
- 至少创建
types.ts、wd-<component>.vue、index.scss。
- 如组件需全局识别,补充
global.d.ts。
- 保持最小可运行骨架,不把 Demo、测试、文档强行塞入同一任务。
- 完成后至少校验当前新增或修改文件无明显语法错误。
| 最低版本 | Min Version |
8. 配置文档侧边栏
需要在以下两个文件中添加侧边栏配置:
中文侧边栏 (docs/.vitepress/locales/zh-CN.ts)
{
link: '/component/{组件名}',
text: '{组件名帕斯卡} {中文名}'
}
英文侧边栏 (docs/.vitepress/locales/en-US.ts)
{
link: '/en-US/component/{组件名}',
text: '{组件名帕斯卡} {英文名}'
}
分类参考:
- 基础:Button、Icon、Popup、Transition 等
- 导航:Pagination、Tabs、Tabbar、Navbar 等
- 数据输入:Input、Picker、Calendar、Form 等
- 反馈:Toast、Loading、ActionSheet 等
- 数据展示:Badge、Card、Cell、Tag 等
9. 创建演示页面 (src/subPages/{组件名驼峰}/Index.vue)
<template>
<page-wraper>
<view class="page-{组件名}">
<demo-block :title="$t('jiBenYongFa')">
<wd-{组件名}>基本用法</wd-{组件名}>
</demo-block>
<demo-block :title="$t('otherFeature')">
<!-- 其他功能演示 -->
</demo-block>
</view>
</page-wraper>
</template>
<script lang="ts" setup>
// 组件逻辑
</script>
<style lang="scss" scoped>
.page-{组件名} {
// 页面样式
}
</style>
注意:使用 page-wraper 组件包裹页面,使用 demo-block 组件分块展示功能
10. 配置演示页面路由 (src/pages.json)
在 subPackages 的 pages 数组中添加:
{
"path": "{组件名驼峰}/Index",
"name": "{组件名驼峰}",
"style": {
"mp-alipay": {
"allowsBounceVertical": "NO"
},
"navigationBarTitleText": "{组件名帕斯卡} {中文名}",
"navigationBarTitleText": "%{组件名小写}-title%"
}
}
11. 配置首页入口 (src/pages/index/Index.vue)
在对应分类的 pages 数组中添加演示页面入口:
{
id: '{组件名驼峰}',
name: t('{组件名小写}-{中文名}')
}
分类对应关系:
| 分类 ID | 说明 | 示例组件 |
|---|
widget | 基础 | Button、Icon、Popup |
nav | 导航 | Tabs、Tabbar、Navbar |
form | 数据输入 | Input、Picker、Calendar |
feedback | 反馈 | Toast、Loading、ActionSheet |
show | 数据展示 | Badge、Card、Cell、Img |
检查清单
创建组件后,确保完成以下事项:
组件代码
类型声明
文档
演示页面