从0到1搭建一个属于自己的组件库

为什么要写一个组件库?

因为随着技术的不断提升,慢慢会到技术瓶颈期,很长一段时间不会有大提升。会不想研究新的东西,不想研究新的方法,新的api,不想学习新的技术,从而陷入技术瓶颈,这个时候可以尝试写一个属于自己的组件库,写完之后会有很大的提升。

搭建项目

  • 选择框架
    可以选择一个自己喜欢或者自己熟悉的框架写一套组件库,我选择的是react。
  • 组件库工具
    可以根据自己选择的框架选择组件库工具,市面上比较流行的 2 个组件库工具分别的 dumi 和 Storybook。这里使用的是dumi ,是一款为组件开发场景而生的文档工具,与 father 一起为开发者提供一站式的组件开发体验,father 负责构建,而 dumi 负责组件开发及组件文档生成。
  • 创建项目
# 先找个地方建个空目录。
$ mkdir myapp && cd myapp

# 通过官方工具创建项目,选择你需要的模板
$ npx create-dumi

# 选择一个模板
$ ? Pick template type › - Use arrow-keys. Return to submit.
$ ❯   Static Site # 用于构建网站
$     React Library # 用于构建组件库,有组件例子
$     Theme Package # 主题包开发脚手架,用于开发主题包

# 安装依赖后启动项目
$ npm start
  • 代码规范
    我这里使用的是ESLint 是一个广泛使用的 JavaScript 代码检查工具,可用于帮助开发者维持一致的代码风格,并捕获潜在的错误和不良习惯。它可以在开发过程中自动检测和纠正代码规范和错误,以确保高质量的代码,下面是一些基础配置:
// 安装eslint
yarn add eslint eslint-plugin-react eslint-plugin-simple-import-sort eslint-plugin-unused-imports @typescript-eslint/eslint-plugin @typescript-eslint/parser -D 
// 添加 .eslintrc.js 配置文件
module.exports = {env: {browser: true,es2021: true,},extends: ["eslint:recommended","plugin:react/recommended","plugin:@typescript-eslint/recommended",],overrides: [],parser: "@typescript-eslint/parser",parserOptions: {ecmaVersion: "latest",sourceType: "module",},plugins: ["react","@typescript-eslint","unused-imports","simple-import-sort",],rules: {"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off","unused-imports/no-unused-imports": "warn","unused-imports/no-unused-vars": ["warn",{vars: "all",varsIgnorePattern: "^_",args: "after-used",argsIgnorePattern: "^_",},],"simple-import-sort/imports": "warn","simple-import-sort/exports": "warn","react/react-in-jsx-scope": "off","react/prop-types": "off",},
}; 
// 修改 packages.json
"scripts": {"eslint": "eslint src --fix",} 
  • git提交规范
    如果涉及到多人开发或者项目开源的话,可以规定提交规范,我这里使用的是commit提交规范,下面是一些常用的提交规范:

commitlint 可以使用这个依赖检查提交规范,方便团队开发合作。

feat:新功能
fix:修复 bug
docs:文档更新
style:代码风格调整,如空格、格式等
refactor:代码重构
test:添加或修改测试
chore:构建过程或辅助工具的变更
  • 配置路由
    .umirc.ts配置文件编写路由配置
    可以按照我这样配置路由
import { defineConfig } from 'dumi';

export default defineConfig({
  // 网站标题名
  title: 'pear-element',
  // 网站标题旁边图片
  favicon:
    'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
  // 页面上展示的logo的图片
  logo: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
  // 打包发布上线的 文件包名字
  outputPath: 'docs-dist',
  // 配置导航条模式 // 默认纵向,
  mode: 'site',
  apiParser: {
    // 自定义属性过滤配置,也可以是一个函数,用法参考:https://github.com/styleguidist/react-docgen-typescript/#propfilter
    propFilter: {
      // 是否忽略从 node_modules 继承的属性,默认值为 false
      skipNodeModules: true,
      // 需要忽略的属性名列表,默认为空数组
      skipPropsWithName: ['autoFocus', 'form', 'formAction', 'formEncType', 'title'],
      // 是否忽略没有文档说明的属性,默认值为 false
      skipPropsWithoutDoc: false,
    },
  },
  history: {
    type: 'hash',
  },
  navs: [
    // null, // 保留默认配置
    {
      title: '指南',
      path: '/guide',
    },
    {
      title: '组件',
      path: '/component',
    },
    {
      title: '作者',
      children: [
        {
          title: 'CSDN',
          path: '地址',
        },
        {
          title: '掘金',
          path: '地址',
        },
      ],
    },
    {
      title: 'GitHub',
      path: '地址',
    },
  ],
});

  • 创建组件
    可以按照我这种使用ts+tsx+less创建组件

src下创建组件文件,demo下写组件使用方法,测试组件,index,md配置路由和需要显示的组件使用示例,API文档等,index.module.less模块化导入组件样式,防止样式冲突,index.tsx组件源代码,interface.ts创建变量类型供源代码使用,规定变量类型,方便管理。

在这里插入图片描述

  • 组件具体编写过程

下面是我的一个组件实现过程,源码和使用示例

demo/index1.tsx

import React from 'react';
import Button from '../index';

export default function ButtonDemo1() {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-around' }}>
      <Button type="primary" >基础按钮</Button>
      <Button type="success">成功按钮</Button>
      <Button type="danger">危险按钮</Button>
      <Button type="warning">警告按钮</Button>
      <Button type="info">信息按钮</Button>
    </div>
  );
}

index.md

---
title: Button按钮
nav:
  title: Basic 基础组件
  path: /component
group:
  path: /basic
---

# Buttoon 按钮

> 常用的 button 按钮

### 基础用法

> 基本使用 button 组件用法

<code src="./demo/index1.tsx" />

### 设置宽高

> 可以通过设置 width 和 height 设置按钮宽高

<code src="./demo/index2.tsx" />

### 设置圆角

> 可以通过设置 radius 设置按钮圆角

<code src="./demo/index3.tsx" />

### 文本按钮

> 可以通过设置 radius 设置按钮圆角

<code src="./demo/index4.tsx" />

### 禁用按钮

> 可以通过设置 forbidden 设置按钮状态

<code src="./demo/index5.tsx" />

### 设置事件

> 可以通过设置 handleClick 绑定自定义事件

<code src="./demo/index6.tsx" />

### button 参数说明

<API />

index.mudule.less

.sussecc {
  padding: 10px 20px;
  background-color: green;
  // border-radius: 10px;
}

.button {
  display: inline-block;

  button {
    box-sizing: border-box;
    color: #fff;
    border: none;
    border: 1px solid;
    outline-style: none;
    cursor: pointer;
  }

  .danger {
    background-color: #fa6060;
    border-color: #fa6060;
    &:hover {
      background-color: #f59b9b;
      border-color: #f59b9b;
    }
    &.disabled {
      background-color: #f6b6b6;
      border-color: #f6b6b6;
      cursor: not-allowed;
    }
  }
  .warning {
    background-color: #f3dd15;
    border-color: #f3dd15;
    &:hover {
      background-color: #f8e74b;
      border-color: #f8e74b;
    }
    &.disabled {
      background-color: #f7ec90;
      border-color: #f7ec90;
      cursor: not-allowed;
    }
  }
  .text {
    color: #000;
    background-color: #fff;
    border-color: #fff;
    &:hover {
      color: #9be4fa;
      background-color: #fff;
    }
    &.disabled {
      color: #d6d7d9;
      cursor: not-allowed;
    }
  }
  .primary {
    background-color: #86e0fb;
    border-color: #86e0fb;
    &:hover {
      background-color: #9be4fa;
      border-color: #9be4fa;
    }
    &.disabled {
      background-color: #b9e9f7;
      border-color: #b9e9f7;
      cursor: not-allowed;
    }
  }
  .info {
    background-color: #b1b3b8;
    border-color: #b1b3b8;
    &:hover {
      background-color: #b9babe;
      border-color: #b9babe;
    }

    &.disabled {
      background-color: #dee0e4;
      border-color: #d6d7d9;
      cursor: not-allowed;
    }
  }
  .success {
    background-color: #5dd105;
    border-color: #5dd105;

    &:hover {
      background-color: #63df03;
      border-color: #63df03;
    }
    &.disabled {
      background-color: #ccf9a9;
      border-color: #ccf9a9;
      cursor: not-allowed;
    }
  }
}

index.tsx

import React, { FC, memo } from 'react';
import Css from './index.module.less';
import { ButtonProps } from './interface';

const Button: FC<ButtonProps> = memo(
  ({ type, children, width, height, radius, handleClick, disabled }) => {
    let style = {
      width: '',
      height: '',
      borderRadius: '',
    };

    if (
      !type &&
      type !== 'danger' &&
      type !== 'warning' &&
      type !== 'success' &&
      type !== 'text' &&
      type !== 'info'
    ) {
      type = 'primary';
    }

    if (width) {
      if (typeof width === 'string') {
        if (width.includes('%') || width.includes('px')) {
          style.width = width;
        }
      } else if (width * 1) {
        style.width = width + 'px';
      }
    } else {
      style.width = '100px';
    }

    if (height) {
      if (typeof height === 'string') {
        if (height.includes('%') || height.includes('px')) {
          style.height = height;
        }
      } else if (height * 1) {
        style.height = height + 'px';
      }
    } else {
      style.height = '45px';
    }

    if (radius) {
      if (typeof radius === 'string') {
        if (radius.includes('%') || radius.includes('px')) {
          style.borderRadius = radius;
        }
      } else if (radius * 1) {
        style.borderRadius = radius + 'px';
      }
    }

    let className = [Css[type], disabled ? Css['disabled'] : ''].join(' ');

    return (
      <div className={Css.button}>
        <button
          style={style}
          className={className}
          onClick={
            !disabled
              ? () => {
                  handleClick ? handleClick() : null;
                }
              : () => {}
          }
        >
          <span>{children ? children : '按钮'}</span>
        </button>
      </div>
    );
  },
);

export default Button;

interface.ts

export interface ButtonProps {
  /**
   * @description 按钮类型 可选值 primary / danger / warning / success /info / text
   * @default primary
   */
  type?: string;
  /**
   * @description 宽度
   * @default 100px
   */
  width?: any;
  /**
   * @description 高度
   * @default 45px
   */
  height?: any;
  /**
   * @description 圆角
   */
  radius?: any;
  /**
   * @description 自定义点击事件
   */
  handleClick?: Function;
  /**
   * @description 禁用
   * @default false
   */
  disabled?: boolean;
  children?: any;
}

发布

  • npm发布

发布时可能会出现很多文件可以慢慢排查,去npm查看包名是否冲突,更新包时查看版本是否更新,查看入口文件路径是否正确,是否时打包后的文件入口。

//打包文件
# npm run build
// 登录npm账号
# npm logo
// 修改镜像源
# npm config set registry https://registry.npmjs.org
// 关联包
# npm link
// 发布到npm
# npm publish
  • 代码托管

我使用的是github代码托管平台,管理代码和部署在线文档。

// 运行这个指令自动上传到github 如果失败,请分步骤上传先打包在上传
# npm run deploy

github部署在线文档方法很简单,在标记处配置部署分支即可,等待配置完成点击上面网站即可跳转到你的在线文档地址。

在这里插入图片描述

这个时候我们就从0到1搭建一个属于自己的组件库,中间的难点就一些文档和代码的规范,一些npm发布流程和github部署流程。

搭建一个属于自己的ChatGPT,需要进行以下步骤: 1. 准备数据集:首先需要有一个聊天数据集,可以在网上搜索或者自己手动收集。数据集应该尽可能多样化,包括不同主题、语言、口音等。数据集可以是文本格式,也可以是语音格式。 2. 安装Python:ChatGPT是基于Python语言开发的,因此需要先安装Python。可以从官网下载安装包,或者使用Anaconda等Python环境管理工具。 3. 安装依赖:ChatGPT需要一些Python的支持,如TensorFlow、Keras、NLTK等。可以使用pip命令安装这些,例如:pip install tensorflow,pip install keras,pip install nltk。 4. 训练模型:使用准备好的数据集进行模型训练。可以选择使用预训练的GPT模型进行fine-tuning,也可以从头开始训练一个新的模型。训练时需要设置一些超参数,如batch size、learning rate、epoch等。 5. 部署模型:训练完成后,需要将模型部署到自己的笔记本上。可以使用Flask等框架开发一个简单的Web应用,接收用户输入的文本或语音,调用模型进行预测,然后返回结果给用户。 6. 测试和优化:部署完成后,需要进行测试和优化。可以使用一些测试工具进行压力测试,检查模型的性能和稳定性,并根据测试结果优化模型和应用程序。 总之,搭建一个属于自己的ChatGPT需要进行一些技术上的操作,需要一定的编程能力和经验。如果没有相关经验,可以参考一些开源的ChatGPT项目,或者使用一些已经开发好的聊天机器人平台。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值