-
Notifications
You must be signed in to change notification settings - Fork 289
Vue DevUI 组件库规范文档
行言 edited this page May 9, 2022
·
4 revisions
- API表格规范
- 组件API规范
- 演示demo规范
- 编码规范
- 组件目录/文件规范
- 样式命名规范
- API部分应该遵循参数、事件、方法、插槽、类型定义的顺序,若某一项缺失则跳过;如果组件有特殊项需要说明,需要在类型定义后面编写。
- API表格的标题,组成格式为:
Xxx [参数 | 事件 | 方法 | 插槽]
,Xxx
为组件名字,采用大驼峰书写,需要注意组件名字后面加一个空格,标题等级为三级;类型定义标题的格式为Xxx 类型定义
,组件名字同样为大驼峰格式,中间同样需要加一个空格,标题等级同样为三级,具体类型名字跟随在后面用四级标题定义。 - API表格表头和内容应该左对齐。
- 参数表格需要具备的列名及顺序为:参数名、类型、默认值、说明、跳转Demo。
- 参数不需要使用反引号。
- 类型需要使用反引号包裹;类型需准确,简单枚举值类型可直接列出来,复杂一些的类型可以写类型名字(如
SizeType
),然后增加锚点定位;参数基本类型采用首字母小写string
,自定义类型名字采用大驼峰命名,(如SizeType
)。 - 默认值不需要反引号包裹,如果默认值为字符串或者枚举类型,应该使用单引号包裹,若无默认值则用双横线
--
表示。 - 说明中需要标注该参数为必选还是可选。
- 跳转Demo中的链接需能够正确跳转,并且demo中需要展示对应API的用法;若无展示Demo,则空白展示。
- 事件表格需要具备的列名及顺序为:事件名、回调参数、说明、跳转Demo。
- 事件名不需要使用反引号。
- 回调参数需要使用反引号包裹;类型格式为
Function(name: string)
。 - 跳转Demo中的链接需能够正确跳转,并且demo中需要展示对应API的用法;若无展示Demo,则空白展示。
- 方法表格需要具备的列名及顺序为:方法名、类型、说明。
- 方法名不需要使用反引号。
- 类型需要使用反引号包裹。
- 插槽表格需要具备的列名及顺序为:插槽名、说明、参数。
- 默认插槽也需要做说明,并且插槽名字应该为
default
。 - 参数为组件内部暴露出来的数据。
- 默认插槽也需要做说明,并且插槽名字应该为
- 类型定义需要使用
typescript
代码块,代码块格式为type xxx = yyy
。
- 命名方式用中划线风格:组件的参数名和事件名统一使用中划线格式。
- 组件名称前缀:组件的命名统一使用
D
前缀。 - 针对需要双向绑定的参数,需要直接用
v-model
,避免增加额外参数,例如v-model:xxx
。 - 原生支持的属性尽量不再用API去单独声明,直接通过
attrs
透传即可,比如placeholder
。
- 演示demo需要对所使用的API及组件默认行为和样式等进行尽可能详细的说明。避免让用户自己去推测,降低用户学习和使用成本。
- 每个组件的第一个demo,应该是组件最基本的用法,即展示组件在不传参数或者传入最基本参数情况下的效果。后面的demo应该尽可能按照参数的使用频率来排序。
- 每个demo所展示的API应该尽量精简,尽量不要一个demo中展示多个API的用法。
- 当API是枚举值时,demo中应尽量展示每个枚举值的效果。
- 演示demo代码,组件的参数大于三个或单行过长时需要每个参数占用一行来展示,避免出现横向滚动条,。
- 演示demo自定义class样式,命名格式为
xxx-demo-yyy
(xxx为组件名,yyy为自定义样式名),不然会成为全局样式,有可能影响其他组件或者demo效果。 - 文案描述需清晰,尽量参考ng devui的文案描述,尽量避免口语化;标点符号使用需正确;文案中若涉及到英文单词,需在单次左右两侧加一个空格。
- 一个标题尽量展示一个demo,避免一个标题中展示多个demo。
-
boolean
类型的参数,在demo中展示,设置为true
的时候,不需要显式的设置为true
,直接写参数名字即可。 - demo的描述说明文案中,用到代码块的地方需要用反引号包裹。
- demo的描述说明文案应该跟在
:::demo
后面,不应该放在h4
或其他标签中,也不应该放在代码块外面。 - 【何时使用】标题等级应该为四级。
- 安装VSCode插件CodeMetrics,原则上函数圈复杂度不超过20。
- 正确定义和使用TS类型,代码无TS类型报错。
- 变量采用语义化命名,原则上不需要通过注释说明变量或函数功能。
- 需注意逻辑和结构的拆分,原则上函数不应该超过50行。
- 目录下的子目录和文件数之和不超过10个。
- 原则上单个文件的代码行数不超过200行。
- 代码单行长度不超过140个字符。
- 代码块嵌套深度不超过4层。
- 组件
props
需在xx-types.ts
文件中定义,并且导出相关参数和props
的类型。 - 代码中不应该出现未使用的变量和依赖。
- 代码中不应该出现
console
等调试信息。 - 在
setup
函数返回的render
函数中定义组件的DOM
结构,而不是用单独的render
函数来定义。 - 需要在组件的
index.ts
文件导出组件参数的类型,方便业务在使用组件时,利用组件导出的参数类型。 - 组件的
import
列表大致遵循以下几个原则:- 最上面应该是依赖的三方库,例如
vue
;中间部分是依赖的组件库的类型文件、子组件、工具函数等;最后一部分是依赖的样式。 - 对于同一个库中的依赖,按照字典序排列,比如
vue
依赖中的defineComponent
需要排在ref
前面。 - 中间部分的引入顺序为类型文件、子组件、工具函数。
- 最上面应该是依赖的三方库,例如
- 需要区分从
vue
中引入的api和类型,对于类型的引入,需要通过import type
引入,例如import type { Ref } from 'vue'
,类型引入应该紧跟在api引入的后面。 -
defineComponent
参数顺序为name
、props
、emits
、inheritAttrs
、setup
。components
和directives
不需要在组件内显示声明。 - 变量和函数的声明顺序需要按照字典序排列。
- 整体目录结构
- 组件文件
my-component.tsx
- 组件入口文件
index.ts
- 组件类型文件规范
my-component-types.ts
- Composable规范
useMyComponent.ts
- 样式文件规范
my-component.scss
- 单元测试文件规范
my-component.spec.ts
my-component
├── __tests__ // 组件单元测试
| └── my-component.spec.ts
├── index.ts // 组件入口文件
└── src // 组件源码
└── components // 子组件
├── my-sub-component.ts
└── composables // 组件的逻辑部分 composable
├── my-use-component.ts
├── my-component-types.ts // 组件类型文件
├── my-component.scss // 组件样式
└── my-component.tsx // 组件
import { defineComponent, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { myComponentProps, MyComponentProps } from './my-component-types';
import useMyComponent from './use-button';
import './my-component.scss';
export default defineComponent({
name: 'DMyComponent',
props: myComponentProps,
emits: ['update:modelValue'],
setup(props: MyComponentProps, ctx: SetupContext) {
const { myProp } = toRefs(props);
const { myUseVar, myUseMethod } = useMyComponent(myUseParam);
return () => {
return (
<div class="devui-my-component">{ myProp.value }</div>
);
};
},
});
import type { App } from 'vue';
import MyComponent from './src/my-component';
export * from './src/my-component-types';
export { MyComponent };
export default {
title: 'MyComponent 我的组件',
category: '通用',
status: '100%',
install(app: App): void {
app.component(MyComponent.name, MyComponent);
},
};
import { PropType, ExtractPropTypes } from 'vue';
export const myComponentProps = {
myProp: {
type: Number,
default: 1
},
myProp2: {
type: Array as PropType<number[]>,
default: [5, 10, 20, 50]
},
} as const;
export type MyComponentProps = ExtractPropTypes<typeof myComponentProps>;
import { ref } from 'vue';
export default function useMyComponent(myUseParam) {
const myUseVar = ref(xxx);
const myUseMethod = () => {
};
return { myUseVar, myUseMethod };
}
@import '../../styles-var/devui-var.scss';
.devui-my-component {
}
import { mount, DOMWrapper } from '@vue/test-utils';
import { ref } from 'vue';
import DMyComponent from '../src/my-component';
describe('MyComponent', () => {
it('should render correctly', async () => {
const wrapper = mount({
components: { DMyComponent },
template: `
<d-my-component my-prop="xxx" />
`,
setup() {
const myVar = ref(xxx);
return { myVar };
}
});
expect(xxx).toEqual(xxx);
});
});
在use-namespace
文件中,封装了样式命名的相关方法。样式命名采用BEM规范,use-namespace
提供了如下几个方法:
// 以 Button 组件为例
// 创建 Button 组件的命名空间
const ns = useNamespace('button');
// 根组件一般采用此命名
ns.b(); // devui-button
// 组件内的块元素样式命名,即 BEM 规范的 Element 部分
ns.e('content'); // devui-button__content
// 组件的修饰类样式命名,即 BEM 规范的 Modifier 部分
ns.m('primary'); // devui-button--primary
// 块元素和修饰类样式组合使用
ns.em('content', 'primary'); // devui-button__content--primary
目前use-namespace
只封装了如上几个方法,在使用中如有新的需求可继续丰富扩展。
在使用use-namespace
重构样式命名的时候,tsx
文件中采用如上几个方法进行重命名,scss
中修改对应的样式名字即可。