# React组件库

  1. Ant Design (opens new window)
  2. Ant Design Mobile (opens new window)
  3. umi官网文档 (opens new window)
  4. create react app配置 (opens new window)

面试点: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

解析:

  1. 根据CSS3规范 (opens new window),视口单位主要包括以下4个:

    • vw:1vw等于视口宽度的1%
    • vh:1vh等于视口高度的1%
    • vmin:选取vw和vh中最小的那个
    • vmax:选取vw和vh中最大的那个
  2. create react app支持less:

    • 使用eject,修改webpack.config.js
    • 使用react-app-rewired,配置config-overrides.js
Last Updated: 2/6/2022, 3:47:25 PM