بنقرة واحدة
create-component
// 在 wot-ui 项目中创建新组件骨架与必要注册点。用户要求从零创建组件源码、补齐 types.vue.scss 结构或注册全局组件类型时调用;不负责 Demo 页、测试和文档迁移。
// 在 wot-ui 项目中创建新组件骨架与必要注册点。用户要求从零创建组件源码、补齐 types.vue.scss 结构或注册全局组件类型时调用;不负责 Demo 页、测试和文档迁移。
优化 subPages 演示页面中的样式,将硬编码的颜色、字号、间距、圆角等替换为 wot-ui 设计系统语义变量。允许直接使用已全局注入的 variable.scss Sass 变量,也允许使用 CSS 自定义属性;不需要额外引入 variable.scss。消除手写的暗色模式覆盖块,统一使用语义变量实现自适应主题。同时将 class 命名统一为 BEM 规范。
只做组件文档与源码实现的一致性核对或最小修正。用户要求核对 props、events、slots、methods、默认值、命名是否准确,但未要求迁移文档结构、重排 Demo 或升级到新规范时调用。
为组件创建演示页面并统一组织结构。用户要求新建/重构组件 Demo、统一展示顺序或用 demo-group 与 demo-group-item 编排时调用。
为 wot-ui 生成单文件主题 SCSS,并在 App.vue 中挂载语义变量。
迁移组件 Markdown 文档到新规范。用户明确要求迁移文档结构、重排 Demo 章节、合并 Attributes/Options 列、迁移最低版本标记或升级旧文档格式时调用;不用于仅做一致性核对。
统一 Vue 与 wot-ui 组件源码中的注释和命名规范。用户要求规范组件 Props 注释、函数命名、类型说明、变量命名或在创建组件后补齐代码注释时调用;不负责 Demo、测试和文档迁移。
| name | create-component |
| description | 在 wot-ui 项目中创建新组件骨架与必要注册点。用户要求从零创建组件源码、补齐 types.vue.scss 结构或注册全局组件类型时调用;不负责 Demo 页、测试和文档迁移。 |
本技能用于在 wot-ui 项目中创建新的 UI 组件骨架。
默认遵循 wot-ui-component-baseline 中的共享约束,命名与注释细则可配合 vue-comment 使用。
create-demo-page。create-test。migrate-component-doc。每个组件位于 src/uni_modules/wot-ui/components/wd-{组件名}/ 目录下,包含以下文件:
wd-{组件名}/
├── types.ts # 类型定义文件
├── wd-{组件名}.vue # 组件主文件
└── index.scss # 样式文件
mkdir -p src/uni_modules/wot-ui/components/wd-{组件名}
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 = {
// 继承基础 props (customStyle, customClass)
...baseProps,
/**
* 属性描述
* 类型: string
* 默认值: ''
*/
prop1: makeStringProp(''),
/**
* 布尔属性描述
* 类型: boolean
* 默认值: false
*/
disabled: makeBooleanProp(false),
/**
* 数字属性描述
* 类型: number
* 默认值: 0
*/
count: makeNumberProp(0),
/**
* 数字或字符串属性
* 类型: string | number
* 默认值: ''
*/
value: makeNumericProp('')
}
// Props 类型导出
export type {组件名}Props = ExtractPropTypes<typeof {组件名驼峰}Props>
// 如果组件暴露方法,定义 Expose 类型
export type {组件名}Expose = {
/** 方法描述 */
methodName: () => void
}
// 组件实例类型
export type {组件名}Instance = ComponentPublicInstance<{组件名}Expose, {组件名}Props>
| 工具函数 | 用途 | 示例 |
|---|---|---|
makeStringProp(default) | 字符串属性 | makeStringProp('') |
makeBooleanProp(default) | 布尔属性 | makeBooleanProp(false) |
makeNumberProp(default) | 数字属性 | makeNumberProp(0) |
makeNumericProp(default) | 数字或字符串属性 | makeNumericProp('') |
makeArrayProp<T>() | 数组属性 | makeArrayProp<string>() |
makeRequiredProp(type) | 必填属性 | makeRequiredProp(String) |
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' - 样式共享模式index.scss)@use '../../styles/mixin/mixin.scss' as *;
@use '../../styles/variable.scss' as *;
// 定义组件级 CSS 变量(支持主题定制)
${组件名}-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;
// 定义元素 (Element)
@include e(header) {
// .wd-{组件名}__header
}
@include e(content) {
// .wd-{组件名}__content
}
@include e(footer) {
// .wd-{组件名}__footer
}
// 定义状态修饰符 (Modifier)
@include when(disabled) {
// .wd-{组件名}.is-disabled
opacity: $opacity-disabled;
}
@include when(active) {
// .wd-{组件名}.is-active
}
// 定义变体修饰符
@include m(primary) {
// .wd-{组件名}--primary
}
@include m(large) {
// .wd-{组件名}--large
}
}
| 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 | 边框 |
项目提供了多个可复用的组合式函数:
| Composable | 用途 |
|---|---|
useParent | 获取父组件实例 |
useChildren | 管理子组件 |
useLockScroll | 锁定页面滚动 |
useClickAway | 点击外部区域检测 |
useQueue | Toast/Notify 队列管理 |
useTranslate | 国际化 |
使用示例:
import { useLockScroll } from '../composables/useLockScroll'
// #ifdef H5
useLockScroll(() => showPopup.value)
// #endif
uni-app 支持跨平台条件编译:
<!-- 仅 H5 平台 -->
// #ifdef H5
<view>H5 专用内容</view>
// #endif
<!-- 仅微信小程序 -->
// #ifdef MP-WEIXIN
<view>微信小程序专用</view>
// #endif
<!-- 非 App 平台 -->
// #ifndef APP
<view>非 App 内容</view>
// #endif
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。需要在以下两个文件中添加侧边栏配置:
docs/.vitepress/locales/zh-CN.ts)// 在对应分类的 items 数组中添加
{
link: '/component/{组件名}',
text: '{组件名帕斯卡} {中文名}'
}
docs/.vitepress/locales/en-US.ts){
link: '/en-US/component/{组件名}',
text: '{组件名帕斯卡} {英文名}'
}
分类参考:
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组件分块展示功能
src/pages.json)在 subPackages 的 pages 数组中添加:
{
"path": "{组件名驼峰}/Index",
"name": "{组件名驼峰}",
"style": {
"mp-alipay": {
"allowsBounceVertical": "NO"
},
// #ifdef MP
"navigationBarTitleText": "{组件名帕斯卡} {中文名}",
// #endif
// #ifndef MP
"navigationBarTitleText": "%{组件名小写}-title%"
// #endif
}
}
src/pages/index/Index.vue)在对应分类的 pages 数组中添加演示页面入口:
// 在对应分类(如 show 数据展示)的 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 |
创建组件后,确保完成以下事项:
组件代码
types.ts 中所有 props 都有中文注释customClass 和 customStyle 属性--wot-{组件名}-* 格式命名Expose 类型name 选项类型声明
global.d.ts 中添加组件类型声明文档
docs/component/{组件名}.mddocs/en-US/component/{组件名}.mdzh-CN.ts 中添加侧边栏配置en-US.ts 中添加侧边栏配置演示页面
src/subPages/{组件名驼峰}/Index.vuepages.json 中配置页面路由src/pages/index/Index.vue 中添加首页入口