使用react搭建组件库(三)——组件库的搭建

1. 使用命令安装初始化: npx create-react-app myUI --typescript 

2. 组件库使用eslint,

新建 .vscode/settings.json 文件
{
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    { "language": "typescript", "autoFix": true },
    { "language": "typescriptreact", "autoFix": true }
  ]
}
设置scss文件:src/styles/_variable.scss 文件:
 
$white: #fff !default;
!default是用来指定变量默认值的,如果在此之前变量已经赋值,那就不使用默认值,如果没有赋值,则使用默认值。
然后定义色彩:
$blue: #0d6efd !default;
设置系统色:
$primary: $blue !default;
新建scss的入口文件:
src/styles/index.scss
```scss
// config
@import "variables";
//layout
@import "reboot";
```
注意 _variables 和 _reboot 两个文件以下划线开头,这个是告诉scss编译器,这个scss的模块,
无法直接使用,只能 @import 引入。
 
在组件中使用 classname:https://github.com/jedWatson/classnames
 
npm install classnames -D

npm install @types/classnames -D
 
如果对象的key值是变化的,可以采用下面的中括号的形式:[`btn-${btnType}`]

1 // btn, btn-lg, btn-primary
2 const classes = classNames('btn', className, {
3     [`btn-${btnType}`]: btnType,
4     [`btn-${size}`]: size,
5     'disabled': (btnType === 'link') && disabled
6 })

 

 ============

目录结构
- src
  - components
    - Button
      - button.tsx
      - _style.scss
  - styles
    - _reboot.scss
    - _variables.scss
    - index.scss
  - App.jsx
  - index.tsx
  - index.html

其中index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3   <head>
 4     <meta charset="utf-8" />
 5     <meta name="viewport" content="width=device-width, initial-scale=1" />
 6     <title>React App</title>
 7   </head>
 8   <body>
 9     <noscript>You need to enable JavaScript to run this app.</noscript>
10     <div id="root"></div>
11   </body>
12 </html>

其中 index.tsx

1  import React from 'react';
2  import ReactDOM from 'react-dom';
3  import './styles/index.scss';
4  import App from './App';
5  ReactDOM.render(<App />, document.getElementById('root'));

然后 App.jsx

1 import React from 'react';
2 import Button,{btnType,ButtonSize} from './components/Button/button'
3 const App:React.FC = () => {
4     return (
5         <div className = "APP-header">
6             <Button btnType={ButtonType.Primary} size={ButtonType.Large}> hello </Button>
7         </div>
8     )
9
 
styles/index.scss
 
// config
@import "variables";

//layout
@import "reboot";

//mixin
@import "mixin";

// animation
@import "animation";

// button
@import "../components/Button/style";

 

开发 Button/button.tsx
 
import React from 'react'
import classNames from 'classnames'

//创建两个枚举,来描述props定义的值——常量值的属性,也就是props中size和btnType 会取到的值
export enum ButtonSize {
    Large = 'lg',
    Small = 'sm'
}
export enum ButtonType {
    Primary = 'primary' 
    Default = 'default' 
    Danger ='danger' 
    Link = 'link'
}

//创建props的TS类型
interface BaseButtonProps {
  className?: string;
  /**设置 Button 的禁用 */
  disabled?: boolean;
  /**设置 Button 的尺寸 */
  size?: ButtonSize;
  /**设置 Button 的类型 */
  btnType?: ButtonType;
  children: React.ReactNode;
  href?: string;
}

const Button: React.FC<BaseButtonProps> = (props) => {
  const { 
    btnType,
    className,
    disabled,
    size,
    children,//相当于vue中的slot
    href
  } = props

  // btn, btn-lg, btn-primary:className的规定,btn是常类名
  const classes = classNames('btn', {
    [`btn-${btnType}`]: btnType,
    [`btn-${size}`]: size,
    'disabled': (btnType === ButtonType.Link) && disabled
  })
  if (btnType === ButtonType.link && href ) {
    return (
      <a
        className={classes}
        href={href}
        {...restProps}
      >
        {children}
      </a>
    )
  } else {
    return (
      <button
        className={classes}
        disabled={disabled}
      >
        {children}
      </button>
    )
  }
}
//设置默认的props
Button.defaultProps = {
  disabled: false,
  btnType:ButtonType.Default
}

export default Button;

 

因为组件内部用的是原生的 button 和 a 标签,所以外部<Button> 需要支持这两个的基本属性
 
 
 1 import React, { FC, ButtonHTMLAttributes, AnchorHTMLAttributes } from 'react'
 2 import classNames from 'classnames'
 3 
 4 export type ButtonSize = 'lg' | 'sm'
 5 export type ButtonType = 'primary' | 'default' | 'danger' | 'link'
 6 
 7 interface BaseButtonProps {
 8   className?: string;
 9   disabled?: boolean;
10   size?: ButtonSize;
11   btnType?: ButtonType;
12   children: React.ReactNode;
13   href?: string;
14 }
15 /*
16 ButtonHTMLAttributes——是button标签的默认属性值,范性 <HTMLElement> 设置了其元素类型
17 BaseButtonProps & ButtonHTMLAttributes<HTMLElement> 中的 & 是联合类型,表示符合这两个类型
18 但是为了选择这两个属性中的一些属性,使用:Partial< a & b> 的形式
19 */
20 type NativeButtonProps = BaseButtonProps & ButtonHTMLAttributes<HTMLElement>
21 type AnchorButtonProps = BaseButtonProps & AnchorHTMLAttributes<HTMLElement>
22 export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps>
23 /**
24  * 页面中最常用的的按钮元素,适合于完成特定的交互
25  * ### 引用方法
26  * 
27  * ~~~js
28  * import { Button } from 'vikingship'
29  * ~~~
30  */
31 //在这里替换成了ButtonProps,表示props的类型
32 export const Button: FC<ButtonProps> = (props) => {
33   const { 
34     btnType,
35     className,
36     disabled,
37     size,
38     children,
39     href,
40     ...restProps
41   } = props
42   // btn, btn-lg, btn-primary
43   const classes = classNames('btn', className, {
44     [`btn-${btnType}`]: btnType,
45     [`btn-${size}`]: size,
46     'disabled': (btnType === 'link') && disabled
47   })
48   if (btnType === 'link' && href ) {
49     return (
50       <a
51         className={classes}
52         href={href}
53         {...restProps}
54       >
55         {children}
56       </a>
57     )
58   } else {
59     return (
60       <button
61         className={classes}
62         disabled={disabled}
63         {...restProps}
64       >
65         {children}
66       </button>
67     )
68   }
69 }
70 
71 Button.defaultProps = {
72   disabled: false,
73   btnType: 'default'
74 }
75 
76 export default Button;

 

 

posted @ 2020-04-06 12:02  小猪冒泡  阅读(1153)  评论(0编辑  收藏  举报