共计 3160 个字符,预计需要花费 8 分钟才能阅读完成。
最近始终在捣鼓如何搭建 React 组件库,至于为什么会产生这个想法,次要是因为组件库对于前端生态来说究极重要,每一个着眼于久远倒退、看重开发效率的的互联网公司基本上都会量身定制本人的组件库,它的益处不必多说。对于前端工程师而言,去了解以及把握它,能够让咱们在今后的工作中以及应聘过程中多出一项非凡技能,并且对本身的纵向倒退也就是很无利的。上面是我记录我在搭建组件库的过程。
初始化工程
搭建工程不打算采纳 create-react-app 脚手架来搭建,因为脚手架封装好了很多货色,而有些货色对于组件库并不实用,用来搭建组件库过于臃肿,因而我不打算借助任何脚手架来搭建工程。
首先,先创立一个工程文件夹 pony-react-ui,在该文件夹下执行如下命令:
npm init // 生成 package.json | |
tsc --init // 生成 tsconfig.json |
而后,依照如下目录构造初始化工程:
pony-react-ui | |
├── src | |
├── assets | |
├── components | |
├── Button | |
├── Button.tsx | |
└── index.ts | |
└── Dialog | |
├── Dialog.tsx | |
└── index.ts | |
├── styles | |
├── _button.scss | |
├── _dialog.scss | |
├── _mixins.scss | |
├── _variables.scss | |
└── pony.scss | |
└── index.ts // 打包的入口文件,引入 pony.scss,抛出每一个组件 | |
├── index.js // 入口文件,package.json 中 main 字段指定的文件 | |
├── package.json | |
├── tsconfig.json | |
├── webpack.config.js | |
└── README.md |
编写一个 Button 组件
Button 组件应该满足一下需要:
- 不同尺寸
- 不同类型
- 不同色彩
- 禁用状态
- 点击事件
Button.tsx
import React from 'react'; | |
import classNames from 'classnames'; | |
export interface IButtonProps { | |
onClick?: React.MouseEventHandler; | |
// 类型 | |
primary?: boolean; | |
secondary?: boolean; | |
outline?: boolean; | |
dashed?: boolean; | |
link?: boolean; | |
text?: boolean; | |
// 尺寸 | |
xLarge?: boolean; | |
large?: boolean; | |
small?: boolean; | |
xSmall?: boolean; | |
xxSmall?: boolean; | |
// 色彩 | |
success?: boolean; | |
warn?: boolean; | |
danger?: boolean; | |
// 禁用状态 | |
disabled?: boolean; | |
className?: string; | |
style?: React.CSSProperties; | |
children?: React.ReactNode; | |
} | |
export const Button = (props: IButtonProps) => { | |
const { | |
className: tempClassName, | |
style, | |
onClick, | |
children, | |
primary, | |
secondary, | |
outline, | |
dashed, | |
link, | |
text, | |
xLarge, | |
large, | |
small, | |
xSmall, | |
xxSmall, | |
success, | |
danger, | |
warn, | |
disabled, | |
} = props; | |
const className = classNames( | |
{ | |
'pony-button': true, | |
'pony-button-primary': primary, | |
'pony-button-secondary': secondary && !text, | |
'pony-button-outline': outline, | |
'pony-button-dashed': dashed, | |
'pony-button-link': link, | |
'pony-button-text': text && !secondary, | |
'pony-button-text-secondary': secondary && text, | |
'pony-button-round': round, | |
'pony-button-rectangle': noRadius, | |
'pony-button-fat': fat, | |
'pony-button-xl': xLarge, | |
'pony-button-lg': large, | |
'pony-button-sm': small, | |
'pony-button-xs': xSmall, | |
'pony-button-xxs': xxSmall, | |
'pony-button-long': long, | |
'pony-button-short': short, | |
'pony-button-success': success, | |
'pony-button-warn': warn, | |
'pony-button-danger': danger, | |
'pony-button-disabled': disabled, | |
}, | |
tempClassName | |
); | |
return ( | |
<button | |
type="button" | |
className={className} | |
style={style} | |
onClick={onClick} | |
disabled={disabled}> | |
<span className="pony-button__content">{children}</span> | |
</button> | |
); | |
} |
在 Button/index.ts 文件中抛出 Button 组件以及定义的类型
export * from './Button';
这样,一个示例组件就根本实现了,有同学必定会有这么一个疑难,为什么在 Button.tsx 中没有引入它的款式文件_button.scss,而是在应用时引入全局款式或者独自引入_button.scss 呢?
// 独自引入组件款式 | |
import {Button} from 'pony-react-ui'; | |
import 'pony-react-ui/lib/styles/button.scss'; | |
// 全局引入组件款式,打包时抽离进去的款式 | |
import 'pony-react-ui/lib/styles/index.scss'; |
因为这跟款式的权重无关,通过 import 引入的款式权重将低于 JSX 中 className 定义的款式,因而才能够在组件内部批改外部的款式。
举个实例:
import {Button} from 'pony-react-ui'; | |
import 'pony-react-ui/lib/styles/button.scss'; | |
import styles from './index.module.scss'; | |
const Demo = () => (<div className={styles.btnBox}> | |
<Button onClick={submit}>submit</Button> | |
</div> | |
) |
引入组件库中的 Button.scss 和本地的 index.module.scss 在打包后会以 <style></style> 注入到页面中,而且程序必定是:
<style type="text/css"> | |
// Button.scss 的款式 | |
</style> | |
<style type="text/css"> | |
// index.module.scss 的款式 | |
</style> |
因而,index.module.scss 中的款式权重是高于 Button.scss 中的款式,能够在 index.module.scss 中批改 Button.scss 的款式
编写款式
打包输入 UMD 标准
打包输入 es module 标准
docz 生成组件应用文档
公布到 npm 仓库