React 规范

React 基础组件规范

组件的定义方式以实现最大程度上的可组合为优先。

基础结构

对于一个最小的可组合组件来说,大致结构如下:

1
2
3
4
5
6
7
8
interface StepperProps {
current: number;
}

const Stepper: FC<StepperProps> = (props) => {
const { current } = props;
return <div>{current}</div>;
};

组件拆分与组织

对于大型组件需要拆分,namespace 的组织方法已经随着 RSC 兴起被逐步废弃,组件的组织方法只能是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const PreviewHeader: FC = ({ title }) => {
return <div>{title}</div>
}

const PreviewContent: FC = ({ children }) => {
return <div>{children}</div>
}

const PreviewContainer: FC = ({ header, content, footer }) => {
return (
<section>
<header>{header}</div>
<main>{content}</div>
</section>
)
}

通过 slot 的方式来将组件拆分,最大程度上实现可组合。

转发 DOM 属性

尽量暴露足够多的 props,最大程度上保证调用处的方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
interface InputProps extends ComponentProps<"input"> {
label: string;
}

const Input: FC<InputProps> = forwardRef((props, ref) => {
const { label, ...rest } = props;
return (
<label>
{label}
<input {...props} ref={ref} />
</label>
);
});

样式、布局、结构、功能分离

先阐释概念:

  1. 样式:决定外观的部分
  2. 布局:决定位置的部分
  3. 结构:为组件的组成提供视觉锚定的部分
  4. 功能:决定组件的行为的部分

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 决定结构
const PreviewContainer: FC = (props) => {
return (
<section className={classNames("", className)}>
<header>{props.header}</header>
<main>{props.content}</main>
</section>
);
};

// 具体的组件,表达样式
const PreviewButton: FC = (props) => {
return (
<button className={classNames("", className)} {...props}>
{props.children}
</button>
);
};

const AppPreview: FC = (props) => {
return (
<PreviewContainer
header={
<PreviewButton
// 在实际的页面中决定功能
onClick={() => console.log("hello")}
>
hello
</PreviewButton>
}
>
{/* 在此处决定布局 */}
<div className="absolute left-0 top-0 flex flex-col gap-2"></div>
</PreviewContainer>
);
};

React 规范
http://blog.akr.moe/react-spec/
作者
Akara Chen
发布于
2025年2月14日
许可协议