组件库开发 | 青训营笔记

122 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天

青训营大项目笔记

组件库通常而言我们是直接调用的,如vue里面可能用element plus,react里面可能直接用antd,但是如何开发属于我们自己的一套组件库呢?

环境准备

  • 使用git版本控制
  • 使用webpack进行打包
  • 使用dumi生成文档站
  • 使用npm管理包
  • 使用eslint,stylelint,pretty来规范代码格式
  • 使用jtest进行单元测试
  • less进行样式组织

开发过程

一切都是从无到有的,我们团队在开发时考虑到个人技术水平的不一致,而且为了统一和规范,我们先开发了一个button组件,以这个作为最基础的demo在此之上进行开发

比方说我们的目录结构如下

image.png

一个典型的button组件需要导出,在button底下的index.tsx中引入button.tsx并导出,button.tsx作为我们button组件的主要逻辑开发部分,__ test __ 文件夹下存放测试所需内容,组件的测试通常包括能否正确渲染,能否正确进行回调。

组件基本需要配套的站点,所以我们在demos底下存放用于在站点上展示的内容,index.md中是文档站主要内容,里面可以引用demos中的文件,展示效果的同时也可以展示代码片段。

style目录下书写样式相关部分,通常而言是导入全局样式,然后再定制自己的样式,对使用到的新建变量再重新写回到根目录style下。

image.png

如这里的按钮样式

@import './mixins.less';

.l-btn {
  position: relative;
  display: inline-block;
  color: @body-color;
  font-weight: @btn-font-weight;
  line-height: @btn-line-height;
  white-space: nowrap;
  text-align: center;
  vertical-align: middle;
  background-image: none;
  border: @btn-border-width solid transparent;
  box-shadow: @btn-box-shadow;
  cursor: pointer;
  transition: @btn-transition;
  .button-size(@btn-padding-y, @btn-padding-x, @btn-font-size, @border-radius);

  &.disabled,
  &[disabled] {
    box-shadow: none;
    cursor: not-allowed;
    opacity: @btn-disabled-opacity;

    > * {
      pointer-events: none;
    }
  }
}
// type
.l-btn-default {
  .button-style(@white, @gray-400, @body-color, @white, @primary, @primary);
}

.l-btn-primary {
  .button-style(@primary, @primary, @white);
}

.l-btn-info {
  .button-style(@info, @info, @white);
}

.l-btn-warning {
  .button-style(@warning, @warning, @white);
}

.l-btn-danger {
  .button-style(@danger, @danger, @white);
}

.l-btn-text {
  .button-style(transparent, transparent, @body-color);

  box-shadow: none;
}

.l-btn-dashed {
  .button-style(@white, @gray-400, @body-color, @white, @primary, @primary);

  border-style: dotted;
}

.l-btn-link {
  color: @btn-link-color;
  font-weight: @font-weight-base;
  text-decoration: none;
  background-color: transparent;
  box-shadow: none;

  &:hover {
    color: @btn-link-hover-color;
    text-decoration: @link-hover-decoration;
  }

  &:focus,
  &.focus {
    text-decoration: @link-hover-decoration;
    box-shadow: none;
  }

  &:disabled,
  &.disabled {
    color: @btn-link-disabled-color;
    pointer-events: none;
  }
}

// size
.l-btn-lg {
  .button-size(
    @btn-padding-y-lg,
    @btn-padding-x-lg,
    @btn-font-size-lg,
    @btn-border-radius-lg
  );
}

.l-btn-md {
  .button-size(
    @btn-padding-y-md,
    @btn-padding-x-md,
    @btn-font-size-md,
    @btn-border-radius-md
  );
}

.l-btn-sm {
  .button-size(
    @btn-padding-y-sm,
    @btn-padding-x-sm,
    @btn-font-size-sm,
    @btn-border-radius-sm
  );
}

// shape
.l-btn-circle {
  min-width: 32px;
  padding-right: 0;
  padding-left: 0;
  text-align: center;
  border-radius: 50%;
}

.l-btn-round {
  border-radius: 30%;
}

// block
.l-btn-block {
  width: 100%;
}