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;