# React组件库
面试点:antd组件化设计思路是什么?
# 1、简介
# 1、组件库优点
- 推动标准统一(UI设计相关)
- 提高开发效率(工程师无需重新开发单独的组件,直接复用已有的组件库开发业务组件及页面)
- 方便扩展(对组件做改造或者扩展的时候,直接对框架进行升级即可)
- 性能优化:通用组件通过缓存,提升页面加载速度(减少冗余代码,文件体积变小)
# 2、思路
- 自上而下,梳理线上页面,综合统计,从业务角度做拆分,然后细化为粒度更细的组件,反哺现在的移动组件库,逐步完善
- 自下而上,从最新的设计规范出发,对比市面上比较主流的组件库,查缺补漏,完善现有的组件库
# 2、实现
# 1、组件库服务
- 底层框架:react、TypeScript、less/sass、webpack5
- 组件:通用类组件、导航栏组件、布局类组件、录入类组件、展示类组件、反馈类组件、手势类组件等
- 对外输出:中后台组件库、BD工具组件库
# 2、实现细节
技术栈:react + typescript + webpack + less
文档工具:docz、storybook、react-docgen-typescript + react-styleguidist
# 3、代码
信息组件:index.less、index.md、index.tsx、interface.ts
- interface.ts定义输入props属性
- interface.ts定义输出的函数式组件,状态内部封闭可使用hooks
- index.less定义组件对应的样式及动画
- index.md定义相关文档
//interface.ts
export interface MessageProps {
className?: string; //需要传递的class
children?: React.ReactNode; //传递的包裹的内容
type?: string; //对应的标签的内容
isIcon?: boolean; //是否展示图标
isScroll?: boolean; //是否滚动动画
isClose?: boolean; //是否需要关闭按钮
}
//index.tsx
import React, { useEffect, useRef, useState } from "react";
import { InfoCircleOutlined, CloseOutlined } from '@ant-design/icons';
import { MessageProps } from "./interface";
import "./index.less";
const Message: React.FC<MessageProps> = (props: MessageProps) => {
const { className, children, type, isIcon, isScroll, isClose } = props;
const contentRef = useRef<HTMLDivElement>(null)
const [duration, setDuration] = useState("");
const [closeMessageVal, setCloseMessageVal] = useState(true);
//构建class
const getClass = () => {
return `react-impression-mobile-tag
${type}
${isScroll ? "scroll" : ""}
${className || ""}`
}
const closeMessage = () => {
setCloseMessageVal(!closeMessageVal);
}
useEffect(() => {
if(isScroll){
const dom = contentRef.current;
if (dom) {
const { width } = dom.getBoundingClientRect()
setDuration(6 + "s");
}
}
}, [children])
return (
<div className={getClass()}
style={{ display: closeMessageVal ? "block" : "none" }}>
<div
className="textContent"
ref={contentRef}
style={{
animationDelay: duration,
animationDuration: duration ? `0s, ${duration}` : ""
}}
>
{isIcon && <InfoCircleOutlined />}
{children}
{isClose && (
<div className="close" onClick={closeMessage}>
<CloseOutlined />
</div>
)}
</div>
</div>
)
}
Message.defaultProps = {
type: "primary",
isIcon: false,
isScroll: false,
isClose: false
}
export default Message;
//index.less
.scroll {
position: relative;
overflow: hidden;
height: 5.33vw;
&::before{
position: absolute;
left: 0;
background-color: #E5F3FD;
content: " ";
width: 4.27vw;
height: 100%;
z-index: 99
}
&::after{
position: absolute;
right: 0;
background-color: #E5F3FD;
content: " ";
width: 4.27vw;
height: 100%;
z-index: 99
}
.textContent{
white-space: nowrap;
animation-name: run, roop;
animation-iteration-count: 1, infinite;
animation-timing-function: linear;
position: absolute;
}
}
@keyframes run {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
@keyframes roop {
from {
transform: translateX(86.53vw);
}
to {
transform: translateX(-100%);
}
}
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
解析:
根据CSS3规范 (opens new window),视口单位主要包括以下4个:
- vw:1vw等于视口宽度的1%
- vh:1vh等于视口高度的1%
- vmin:选取vw和vh中最小的那个
- vmax:选取vw和vh中最大的那个
create react app支持less:
- 使用eject,修改webpack.config.js
- 使用react-app-rewired,配置config-overrides.js