zoukankan      html  css  js  c++  java
  • 使用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;
  • 相关阅读:
    leetcode刷题-- 4. 贪心
    golang 中的引号
    记录博客的目的
    java返回树形结构的正确姿势
    java -jar xxxx.jar --server.port(指定启动端口无效)
    Spring 中@NotNull, @NotEmpty和@NotBlank之间的区别是什么?
    IntelliJ IDEA远程连接linux,一键上传jar包
    linux 运行Jar包时指定启动端口
    @Validated注解对单个实体类与List集合的验证
    linux -bash: ./startup.sh: /bin/sh^M: 坏的解释器: 没有那个文件或目录
  • 原文地址:https://www.cnblogs.com/xiaozhumaopao/p/12641440.html
Copyright © 2011-2022 走看看