前言
Hello,相信很多朋友在面试的时候肯定会有被面试官问项目亮点的场景并说不出所以然,然而大部分我们都是一颗螺丝钉,包括本人工作中也是经常的CRUD。所以很多时候项目中确实没啥可说的,但是面试官可不想听这个。
见缝插针
相信大家都用过组件库吧,或者自己在components下封装的组件,不管是ElementUI还是Ant Design又或者其他,在现在这个前后端分离的时代少不了UI组件库的加持,所以我们可以从这里开始"插一针"。其实不光只是UI组件库,在工作中可以去观察发现可以"插针的地方",比如我们老生常谈的打包优化 、FCP 、LCP等,没有一个十全十美的项目,需要做的就是找到并解决这就是你的亮点,哪怕只是一点点!
dui项目地址
dui项目地址,这个项目从0-1搭建了一个ui组件库,不过目前一个人精力有限很多有些测试没有做、也可能存在一些bug未修复。不过对于新手学习搭建过程还是可以的,大佬就轻点喷了😬,如果你觉得对你有帮助,麻烦点个star⭐,非常感谢~
技术选型及配置
对于文档这块Vue的小伙伴可以选择VuePress、React技术的同学也可选择dumi。 接下来就是项目初始化,随后配置babel、eslint、prettier等,配置的话可以看站内其他文章还是比较多的。 这里放一下比较重要的rollup的配置。
文件组织及结构
- .github:用github来做ci、cd
- .storybook:storybook相关配置,在打包文档时会读取
- src-components:源码存放的地方,最后通过index.tsx统一导出
- hooks:常用的自定义hook
- storybook-static:构建后的文档目录
搞一个Button玩玩
在项目都初始化完毕后,即可开始我们的源码编写了,以一个最基础的Button为例,如下
js
import React from "react";
import className from "classnames"; //用来拼接class 详情参考:https://github.com/JedWatson/classnames#readme
//ant design 的组件样式基础样式前缀 是 ant 这里我们用 dui eg:dui-btn、dui-btn-primary
//类型别名
export type ButtonType = "default" | "primary" | "link";
export type ButtonSize = "middle" | "small" | "large";
//button 的基础属性
//需要注意当是链接按钮时 type=link ,对应生成的是 a 标签 也可以用button模拟
export interface IBaseButtonProps {
//这里的属性最好不要和 原生属性冲突 ts会报错 eg:type -> btnType
/**设置button类型 */
type?: ButtonType; // button的类型 eg:default、primary、link
danger?: boolean;
/**设置button尺寸 */
size?: ButtonSize; // button的大小 eg: middle、small、large
/**是否禁用 */
disabled?: boolean; // button 的禁用状态 at: a标签是没有disable的属性的
className?: string;
style?: React.CSSProperties;
onClick?: () => void;
children: React.ReactNode; // 用来渲染组件中的内容
}
// button 和 a 标签还有一些其他的属性 如onclick 不能把每一个属性都一一写在上面 这里用React提供的interface然后传入一个泛型
type ButtonProps = React.ButtonHTMLAttributes<HTMLElement>; // button的其他原生属性
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>; // a标签的其他原生属性
type AllOptionalButtonprops = Partial<ButtonProps & AnchorProps>; // 这里用ts的Utility Types Partial将type都转成可选的(用户不一定把所有参数都传入)
//将可选的和 IBaseButtonProps 结合成为最终的 props
export type IButtonProps = AllOptionalButtonprops & IBaseButtonProps;
/**
* 页面中最常用的的按钮元素,适合于完成特定的交互
* ### 引用方法
*
* ~~~js
* import { Button } from 'jadedui'
* ~~~
*/
const Button: React.FC<IButtonProps | IBaseButtonProps> = (props) => {
const {
type = "default",
size = "middle",
danger,
disabled,
children,
className: cusClassname,
...restprops
} = props;
//如果是link类型就生成a标签
const classNames = className(
cusClassname,
"dui-btn",
{ [`dui-btn-${type}`]: true },
{ [`dui-btn-${size}`]: true },
{ [`dui-btn-disabled`]: type === "link" },
{ [`dui-btn-danger`]: danger }
);
if (type === "link") {
return (
<a className={classNames} {...restprops}>
{children}
</a>
);
} else {
return (
<button disabled={disabled} className={classNames} {...restprops}>
{children}
</button>
);
}
};
Button.defaultProps = {
type: "default",
size: "middle",
};
export default Button;
上面基本都有注释,也比较好理解,这里说明antd5采用的是css in js,我们还是用比较传统的做法。创建类名 -> 编写样式。编写好源码后,我们还要编写文档,在同级文件夹下创建xxx.stories.tsx ,storybook会读取该文件并生成文档(前提是你已经配置好storybook所需相关配置)
文档代码
js
import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import Button from "./index";
const defaultButton = () => (
<Button onClick={action("clicked")}> default button </Button>
);
const buttonWithSize = () => (
<>
<Button size="small"> small button </Button>
<Button size="large"> large button </Button>
</>
);
const buttonWithType = () => (
<>
<Button type="primary"> primary button </Button>
<Button danger> danger button </Button>
<Button type="link"> link button </Button>
</>
);
storiesOf("Button按钮", module)
.add("Button", defaultButton)
.add("不同尺寸的Button", buttonWithSize)
.add("不同类型的Button", buttonWithType);
思考
上述是一个ui组件库,在工作中也可将业务组件做成一个组件库,做法肯定不止这一种,比如webpack5模块联邦也可用于通用功能的封装,以及一些开源remote的项目。如果只是停留在使用,那必然是没什么收获和亮点的。
最后
如果你觉得对你有帮助,麻烦点个star⭐,非常感谢 bye~