写给自己看的代码风格规范,让写代码变得更加有章法。
例如: 将文件目录命名为 form-item
而不是 FormItem
。
例如 form-item
组件中,入口文件内容如下:
export * from './src/hoc';
export * from './src/utils';
export * from './src/components';
export * from './src/createSuperFormItem';
入口文件导出最好按照长度排序,好看。
例如 Color.tsx
组件。
例如应该是 Checkbox.tsx
而不是 SuperCheckbox.tsx
。
例如 Checkbox.tsx
对应着 SuperCheckbox
组件。
例如 util.ts
或者 useAxios.ts
例如 SuperCheckbox
组件,其组件属性定义应该为 SuperCheckboxProps
。
在设计函数接口时,请严格遵循以下规则:
- 1、若某函数是公共 API 的一部分,则其可以接受 0~2 个参数,如果必要的话,可以外加一个选项对象,因此最大总数为 3 个。
- 2、可选参数通常应放到选项对象中。如果只有一个可选参数,并且将来一般不会添加更多可选参数,那么该可选参数可以不放在选项对象中。
// 错误示例:可选参数不是选项对象的一部分 (#2)
export function resolve(hostname: string, family?: 'ipv4' | 'ipv6', timeout?: number): IPAddress[] {}
// 正确示例:
export interface ResolveOptions {
family?: 'ipv4' | 'ipv6';
timeout?: number;
}
export function resolve(hostname: string, options: ResolveOptions = {}): IPAddress[] {}
// 错误示例:多于3个参数 (#1),多个可选参数 (#2)。
export function renameSync(oldName: string, newName: string, replaceExisting?: boolean, followLinks?: boolean) {}
// 正确示例
interface RenameOptions {
replaceExisting?: boolean;
followLinks?: boolean;
}
export function renameSync(oldName: string, newName: string, options: RenameOptions = {}) {}
// 错误示例:参数过多 (#1)
export function write(fd: number, buffer: TypedArray, offset: number, length: number, position: number) {}
// 正确示例:
export interface PWrite {
fd: number;
buffer: TypedArray;
offset: number;
length: number;
position: number;
}
export function write(options: PWrite) {}
// form 组件引入 btns 组件 ✅
import { Btns } from '@/btns';
// 不应该从 'supe
import { Btns } from 'super-antd';
';
;
/
import { Btns } from '../btns';
如果可能的话,最好写单行 JSDoc。例如:
/** 这样写单行 JSDoc 注释。 */
export function foo() {
// ...
}
不要写为:
/** 不要这样写单行 JSDoc 注释。 */
代码字符串文字应使用反引号(`)括起来,而不是用引号。例如:
/** Import something from the `super-antd`. */
不要使用 @param
,因为 TypeScript 已经是强类型化的了。
/**
* Function with non obvious param.
*
* @param foo Description of non obvious parameter.
*/
代码示例要和说明之间空一行,并且示例代码的每一行需要有 6 个额外空格。比注释的第一列多 4 个空格。例如:
/**
* A straight forward comment and an example:
*
* import { useAxios } from 'super-antd';
* const { loading } = useAxios({ api });
*/
既然代码示例已经是一个注释了,它就不应再包含其他注释。如果它需要进一步的注释,那意味着它不是一个很好的示例
每个文件都应该有一个测试用例,测试用例文件和测试文件名一一对应。
src
btns
Btns.tsx
# 对应着测试用例应该为
tests
btns
Btns.test.tsx
dumi
提供了 code
标签去引入组件示例的能力,所以我们不应该在 markdown 内部再去写示例。
每一篇文档都需要对应一个文件夹,例如:
form.md
select.md
# 他们的 demo 文件对应着同级目录下的
__demos__
form
hideLabel.tsx
api_basic.tsx
每个文件名都能够表达其基本含义,例如上面 form 组件的 hideLabel
表示 hideLabel
属性对应的功能示例,而 api_basic
表示 api
属性的基本使用方式。
而不应是:
❌
__demos__
form
demo1.tsx
demo2.tsx
XxxProps
专用于 React 组件属性XxxOptions
专用于函数参数XxxxType
非上述两种情况
interface SuperFormProps {
// ...
}
const SuperForm: FC<SuperFormProps> = () => {};
interface GetBtnsOptions {}
function getBtns(options: GetBtnsOptions) {}
export type AlignType = 'left' | 'right' | 'center'; // 其他情况使用 XxxType
interface SuperBtnsProps {
align: AlignType;
}
需要注意的是,一个组件的属性可能有多部分组成,则其他部分也是用 XxxProps
定义。
interface SuperFormItemInjectProps {}
interface SuperFormItemOverwriteProps {}
interface SuperFormItemProps extends SuperFormItemInjectProps, SuperFormItemOverwriteProps {}
具体可以看 useCreation 介绍。
例如 provider
组件:
provider
index.ts # 用于导出所有
src
Provider.tsx # 必须有一个同名的
context.ts
export const foo = 123; // 就算是 export default 也需要 export
export default foo;