farris-vue/style-guide/vue_component_style_guide.md

165 lines
5.3 KiB
Markdown
Raw Normal View History

2022-09-12 14:33:19 +08:00
# Farris UI Vue 组件开发规范
为了保证 Farris UI Vue 的源代码风格一致确保组件研发质量方便社区开发者阅读代码参与贡献需要所有参与Farris UI Vue 组件开发的贡献,都要遵循此组件开发规范。
## 组件目录和文件规范
Farris UI Vue 的组件,都包含在`ui-vue`包的`components`目录下,每一个子组件为独立目录,目录名为全小写的组件名,当组件名包含多个英文单词时,使用`-`分隔。
目录规范分成以下部分:
### 组件目录结构
以下是单个组件目录的结构
```
2022-09-15 20:23:48 +08:00
input-group
├── test // 单元测试
| └── input-group.spec.tsx
├── src // 组件源码
| ├── components // 子组件
2022-09-15 20:23:48 +08:00
| | └── input-group-sub.component.tsx
| ├── composition // 组件的可复用逻辑
| | ├── types.ts // 组合式Api返利值接口类型
| | ├── use-append-button.ts // 实现组件特性1的组合式Api
| | └── use-clear.ts // 实现组件特性2的组合式Api
| ├── input-group.component.tsx // 组件代码
| └── input-group.props.ts // 定义组件Api
2022-09-12 14:33:19 +08:00
└── index.ts // 组件入口文件
```
### 入口文件 `index.ts`
```TypeScript
import type { App } from 'vue';
2022-09-15 20:23:48 +08:00
import InputGroup from './src/input-group.component';
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
export * from './src/input-group.props';
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
export { InputGroup };
2022-09-12 14:33:19 +08:00
export default {
install(app: App): void {
2022-09-15 20:23:48 +08:00
app.component(InputGroup.name, InputGroup);
2022-09-12 14:33:19 +08:00
},
};
```
2022-09-15 20:23:48 +08:00
### 组件文件 `input-group.component.tsx`
2022-09-12 14:33:19 +08:00
```TypeScript
import { defineComponent, toRefs } from 'vue';
import type { SetupContext } from 'vue';
2022-09-15 20:23:48 +08:00
import { InputGroupProps, inputGroupProps } from './input-group.props';
import { useClear } from './composition/use-clear';
2022-09-12 14:33:19 +08:00
export default defineComponent({
2022-09-15 20:23:48 +08:00
name: 'FInputGroup',
props: inputGroupProps,
2022-09-12 14:33:19 +08:00
emits: ['update:modelValue'],
2022-09-15 20:23:48 +08:00
setup(props: InputGroupProps, setupContext: SetupContext) {
2022-09-12 14:33:19 +08:00
const { someProp } = toRefs(props);
2022-09-15 20:23:48 +08:00
const { showClearButton, onClearValue } = useClear();
2022-09-12 14:33:19 +08:00
return () => {
return (
2022-09-15 20:23:48 +08:00
<div class="f-input-group">{ someProp.value }</div>
2022-09-12 14:33:19 +08:00
);
};
},
});
```
2022-09-15 20:23:48 +08:00
### 类型文件 `input-group.props.ts`
2022-09-12 14:33:19 +08:00
```TypeScript
import { PropType, ExtractPropTypes } from 'vue';
2022-09-15 20:23:48 +08:00
export const inputGroupProps = {
/**
* 显示输入框的标签
*/
enableTitle: { type: Boolean, default: false },
/**
* 输入框提示文本
*/
placeholder: { type: String, default: '' },
/**
* 输入框Tab键索引
*/
tabIndex: Number
2022-09-12 14:33:19 +08:00
};
2022-09-15 20:23:48 +08:00
export type InputGroupProps = ExtractPropTypes<typeof inputGroupProps>;
2022-09-12 14:33:19 +08:00
```
2022-09-15 20:23:48 +08:00
### 组合式Api `use-clear.ts`
2022-09-12 14:33:19 +08:00
```TypeScript
2022-09-15 20:23:48 +08:00
import { computed, SetupContext } from 'vue';
import { InputGroupProps } from '../input-group.props';
import { UseClear } from './types';
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
export function useClear(props: InputGroupProps, setupContext: SetupContext): UseClear {
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
function onClearValue($event: Event) {
console.log('on onClearValue');
}
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
return {
showClearButton,
onClearValue
};
2022-09-12 14:33:19 +08:00
}
```
2022-09-15 20:23:48 +08:00
### 单元测试 `input-group.spec.tsx`
2022-09-12 14:33:19 +08:00
```ts
2022-09-15 20:23:48 +08:00
import { mount } from '@vue/test-utils';
import { InputGroup } from '..';
2022-09-12 14:33:19 +08:00
2022-09-15 20:23:48 +08:00
describe('f-input-group', () => {
it('variant', () => {
2022-09-12 14:33:19 +08:00
const wrapper = mount({
setup() {
2022-09-15 20:23:48 +08:00
return () => {
return <InputGroup editable={false}></InputGroup>;
};
},
2022-09-12 14:33:19 +08:00
});
2022-09-15 20:23:48 +08:00
expect(wrapper.find('.f-cmp-inputgroup').exists()).toBeTruthy();
expect(wrapper.find('div').find('div').find('input').find('[readlony]').exists).toBeTruthy();
2022-09-12 14:33:19 +08:00
});
});
```
## 组件编码规范
- 组件采用中划线风格命名,组件的参数名和事件名统一使用中划线格式。
- 所有组件统一在名称前使用`F`前缀,组件选择器前使用`f-`前缀。
- 直接用v-model传递双向绑定的参数。
- 使用属性透传传递原生属性不允许在单独定义API声明原生属性。
- 正确定义和使用TypeScript类型代码中无TypeScript类型报错。
- 变量采用语义化命名,原则上不需要通过注释说明变量或函数功能,详细命名规则参考[Farris UI TypeScript 编码指南](./style-guid/typescript_style_guid.md)。
2022-09-15 20:23:48 +08:00
- 需要将组件的props定义在独立的文件some-component.props.ts文件中并在此文件中同时导出props和PropsType。
2022-09-12 14:33:19 +08:00
- 应该在setup函数返回的render函数中编写组件的Html模板。
- 必须在组件的index.ts文件中导出组件参数的类型以便于在引用组件时方便TypeScript进行类型提示。
- defineComponent函数接收的参数顺序为name、props、emits、inheritAttrs、setup。
- 不要在组件内显式声明components和directives。
- 需要安装字典顺序排列组件的变量。
## 组件文档规范
待上线Doc站点后补充
## 关于
本项目的 Farris UI Vue 组件开发规范遵循[CC-By 3.0协议](https://creativecommons.org/licenses/by/3.0/)。
2022-09-12 14:41:07 +08:00
<a rel="license" href="https://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/3.0/88x31.png" /></a>