3如何搭建组件库的样式工程之button-scss

为什么要搭建样式工程

痛点分析

  • 1:每个组件库都希望命名规范,并且统一
  • 2:搭建一套组件库样式同成功,通过大部分计算,未来更改一些基础配置参数,就可以形成另一套样式。
  • 3:样式工程可以降低代码冗余。
  • 4:我就是希望写一套样式,可以定制出n套组件库

可行性分析

目前有很多公司为了降低人员成本,定制了公司内部组件库。有的公司居于某个组件库二次封装,弊端及时维护升级困难。如果有一套工程化。
大部分公司虽然使用css预处理器,但是也是只写法上与css没什么区别。。。 失去了预处理器真正的作用和价值。
应该向写js脚本一样,能封装就封装,能抽象就抽象

规范

应该从一下几个角度完成样式工程化:

  • 1:统一命名 ----- 推荐用指令封装
  • 2:封装指令和函数,动态生成命名
    • 2.1 作用是什么 -------编译结果
    • 2.2 哪些是动态的-----参数传递
    • 2.3 哪些是静态的-----直接声明好
  • 3:定义一些全局变量和配置变量
    • 配置变量:前缀 连接符 属性连接符 判断前缀
    • 全局变量:基础颜色 变量 字体 背景 …

这里我更加建议,应该在一个完整的设计搞前提下,提前定义好规范

学习角度改如何完成规范:

  • 第一步:先按照规范写好面向过程代码
  • 第二步:从选择器开始找,找重复的代码,3个组件对比找重复代码,然后提取封装为混入,动态生成选择器,下面会有我的封装代码
  • 第三步:看样式,建议单独一个组件看,看有没有重复代码,能不能变为指令,通过混入的方式导入
  • 第四步:在再写内容中,传值估计都是静态,看看能否变为全局变量,理由基础变量来运算得到

学习案例如下:
例如:button alert message三个组件
基础类名相同:.fl-button .fl-alert .fl-message
封装如下:

@mixin BaseName($n){
   $pre:'fl';
   .#{$pre+$n}{
     @content;
   }
}


在 alert中使用如下:

@include BaseName(alert){
}

在 button 组件中使用:

@include BaseName(button){
}

总结:不论是选择器名字,还是样式体中样式;关键都是找相同点在抽离

实战button样式工程化

非工程化代码

.fl-button {
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: white;
  border: 1px solid white;
  border-color: #d9d9d9;
  color: block;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: .1s;
  font-weight: 400;
  margin-left: 10px;
  // 以上代码静态复制,可以提前定义为全局变量并引入
  
   -moz-user-select: none;
   -webkit-user-select: none;
   -ms-user-select: none;
   // 以上代码可以封装为工具指令utils mixin
   padding: 12px 20px;
   font-size: 14px;
   border-radius: 4px;
   &.is-round {
     padding: 12px 14px;
   }
   // 以上代码可以抽离为指令 button-size 属性赋值可以同归参数传递
   .fl-button--success{
  color: $--color-white;
  border-color: $--color-success;
  background-color: $--color-success;
  &:hover,&:focus{
    color: $--color-success;
    border-color: $--color-primary-light-2;
    background-color: $--color-primary-light-5;
  }
}
.fl-button-error{
  color: $--color-white;
  border-color: $--color-error;
  background-color: $--color-error;
  &:hover,&:focus{
    color: $--color-success;
    border-color: $--color-primary-light-2;
    background-color: $--color-primary-light-5;
  }
}
// 以上代码可以抽离两个指令
// 1:创建 状态选择器 指令 m
// 2:创建 不同状态相同代码片段指令  button-variant 
}

当然还有 disable circle 等,上面就不一一编写了

目录如下

|--themes
   |--common
     |--var.scss 全局变量
   |--mixin
     |-- mixin.scss 大部分组件封装混入
     |-- ButtonMixin.scss button中封装混入
     |-- config.scss 全局配置变量
     |-- utils.scc   工具混入
   |--Button.scss

var.scss

// 这里是全局变量文件

  

/* Color

-------------------------- */

$--color-white: #ffff !default;

$--color-black: #000;

  

// 全局基础颜色

$--color-primary: #1890ff !default; // 全局主色

  

$--color-link: #1890ff !default; // 链接色

$--color-success: #52c41a !default; // 成功色

$--color-danger: #faad14 !default; // 警告色

$--color-error: #f5222d !default; // 错误色

$--color-info: #909399 !default;  

  
  

// primary 亮色系列的9个维度

$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */

$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */

$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */

$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */

$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */

$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */

$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */

$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */

$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */

  

// color-text

/// color|1|Font Color|2

$--color-text-primary: #303133 !default;

/// color|1|Font Color|2

$--color-text-regular: #606266 !default;

/// color|1|Font Color|2

$--color-text-secondary: #909399 !default;

/// color|1|Font Color|2

$--color-text-placeholder: #C0C4CC !default;

/// color|1|Border Color|3

  
  

/* 基础字号大小 */

$font-size-base: 14px; // 主字号

$heading-color: rgba(0, 0, 0, 0.85); // 标题色

$text-color: rgba(0, 0, 0, 0.65); // 主文本色

$text-color-secondary: rgba(0, 0, 0, 0.45); // 次文本色

$disabled-color: rgba(0, 0, 0, 0.25); // 失效色

  
  

// font-weight;

$font-weight-primary: 500 !default;

$font-weight-secondary: 100 !default;

  
  

// border-base

$border-radius-base: 4px; // 组件/浮层圆角

$border-color-base: #d9d9d9; // 边框色\

$border-width-base: 1px !default;

$border-style-base: solid !default;

$border-base: $border-width-base $border-style-base  $border-color-base ;

/* border-color */
/// color|1|Border Color|3
$--border-color-light: #E4E7ED !default;
/// color|1|Border Color|3
$--border-color-lighter: #EBEEF5 !default;
/// color|1|Border Color|3
$--border-color-extra-light: #F2F6FC !default;

  

$box-shadow-base: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08),

  0 9px 28px 8px rgba(0, 0, 0, 0.05); // 浮层阴影

  
  

/** Button */
$--button-padding-vertical: 12px !default;
$--button-padding-horizontal: 20px !default;
$--button-font-size: $font-size-base !default;
$--button-border-radius: $border-radius-base !default;
$--button-font-weight: $font-weight-primary !default;
/* type */

// default

$--button-default-background-color: $--color-white !default;

$--button-default-border-color:$border-color-base !default;

$--button-default-font-color: $text-color;

$--button-default-font-weight:$font-weight-primary;

$--button-default-font-size: $font-size-base;

  

// success

$--button-success-border-color: $--color-success !default;

$--button-success-font-color: $--color-white !default;

$--button-success-background-color: $--color-success !default;

$--button-success-font-weight:$font-weight-primary;

$--button-success-font-size: $font-size-base;

  

// error

$--button-error-border-color: $--color-error !default;

$--button-error-font-color: $--color-white !default;

$--button-error-background-color: $--color-error !default;

  

// danger

// /// color||Color|0

$--button-danger-border-color: $--color-danger !default;

$--button-danger-font-color: $--color-white !default;

$--button-danger-background-color: $--color-danger !default;

  

// info

$--button-info-border-color: $--color-info !default;

$--button-info-font-color: $--color-white !default;

$--button-info-background-color: $--color-info !default;

  

// primary

$--button-primary-border-color: $--color-primary !default;

$--button-primary-font-color: $--color-white !default;

$--button-primary-background-color: $--color-primary !default;

  
  

/* size */

  

// medium

/// fontSize||Font|1

$--button-medium-font-size: $font-size-base !default;

/// borderRadius||Border|2

$--button-medium-border-radius: $border-radius-base !default;

/// padding||Spacing|3

$--button-medium-padding-vertical: 10px !default;

/// padding||Spacing|3

$--button-medium-padding-horizontal: 20px !default;

  

// small

/// fontSize||Font|1

$--button-small-font-size: 12px !default;

$--button-small-border-radius: #{$border-radius-base - 1} !default;

/// padding||Spacing|3

$--button-small-padding-vertical: 9px !default;
/// padding||Spacing|3
$--button-small-padding-horizontal: 15px !default;
// mini

/// font-size||Font|1

$--button-mini-font-size: 12px !default;

$--button-mini-border-radius: #{$border-radius-base - 1} !default;

/// padding||Spacing|3

$--button-mini-padding-vertical: 7px !default;

/// padding||Spacing|3

$--button-mini-padding-horizontal: 15px !default;

  
  
  

/* disable */

/// color||Color|0

$--button-disabled-font-color: $--color-text-placeholder !default;

/// color||Color|0

$--button-disabled-background-color: $--color-white !default;

/// color||Color|0

$--button-disabled-border-color: $--border-color-lighter !default;

  

$--button-hover-tint-percent: 20% !default;

config.scss

// 解决是统一命名的问题

$namespace: 'fl'; // 组件库样式的标识,
$base-separator:'-';// 命名空间与元素分隔符  例如 fl-button fl-form
$element-separator: '__'; // 元素分割符号
$modifier-separator: '--'; // 修饰分割符号,【添加样式命名用修饰分割术】
$state-prefix: 'is-'; // 状态前缀

mixin.scss

@import './config.scss';
// BaseName 基础命名
@mixin BaseName($block){
    // !global 让$name 变为一个全局变量,在任意的位置都可以访问
    $name:$namespace+$base-separator+$block !global;
    .#{$name}{
        @content;
    }
}

/*
1:作用:处理组件中,状态属性的命名:例如 .fl-button--success .fl-button--error
2: 编译结果,选择器有效,全局的,不需要父选择器
3:适用:某个组件,在不同状态下有不同样式,可以在@include BaseName(){内部是哟i给你}
*/
// 为什么写m指令 解决了哪些问题????
@mixin m($type){
    //bug >>>> 注意: 作为子沦入指令,!global 失效,应该用@at-root
    $currentSelect:'' ;// 求得到的选择器
    $preSelect:&;
    @each $unim in $type {
        $currentSelect:$currentSelect + $preSelect+$modifier-separator+$unim
    }
    // 解决: !global 失效问题
    @at-root {
        #{$currentSelect} {
            @content;
        }
    }
}
@mixin when($state) {
    @at-root {
      &.#{$state-prefix + $state} {
        @content;
      }
    }
}

ButtonMixin.scss

@import './common/var.scss';

@import './mixin/mixin.scss';

@import './mixin/utils.scss';

@import './mixin/buttonMixin.scss';

// 1:创建全局变量

//    1.1 基础变量

//      - 状态基础颜色

//      - 每个颜色都有高亮显示梯度,9个维度,用mix 函数 根据基础颜色计算得到

//      - 边框 宽度 样式 颜色

//      - font   size  weight  family

//    1.2 选择命名的变量:(为了命名统一性和统一风格)

//      - 1:命名空间 fl

//      - 2: 链接符号   -

//      - 3:状态链接符号 --

//      - 4:元素链接符号 __


@include BaseName(button){

  // 1:为社么写这里?

  // 清空button的默认样式

  display: inline-block;

  line-height: 1;

  white-space: nowrap;

  cursor: pointer;

  background: $--button-default-background-color;

  border: $border-base;

  border-color: $--button-default-border-color;

  color: $--button-default-font-color;

  -webkit-appearance: none;

  text-align: center;

  box-sizing: border-box;

  outline: none;

  margin: 0;

  transition: .1s;

  font-weight: $--button-default-font-weight;

  margin-left: 10px;

  

  // 为什么写这个

  // 禁止鼠标选中文本 禁止鼠标右键点击

  @include utils-user-select(none);

  

  // button-size 为什么这些写,代码由来是什么

  /*

   1 因为 button 按钮有 大 中 小 默认;其他大小未来可以通过央视覆盖方式实现

   2 为了降低代码重复率,所以封装为混入

   3 因为内边距 大小 都是有统一规格的,最好通过变量引用方式白那些

  */

  // 设置大小,button 按钮有 大 中 小 默认 4个型号所以重复执行-->混入

  // @include button-size(12px,24px,14px,2px)

  

  @include button-size($--button-padding-vertical, $--button-padding-horizontal, $--button-font-size, $--button-border-radius);

  &:hover,

  &:focus {

    color: $--color-primary;

    border-color: $--color-primary-light-7;

    background-color: $--color-primary-light-9;

  }

  

   // .fl-button.is-disable

  @include when(disable){

    &,

    &:hover,

    &:focus {

      color: $--button-disabled-font-color;

      cursor: not-allowed;

      background-image: none;

      background-color: $--button-disabled-background-color;

      border-color: $--button-disabled-border-color;

    }

    // type 样式失效

  }

  

  // 需求:既需要卸载这里, 又希望是全局选择器

  // .fl-button--success {}

  // &--success{}

  // &=== .fl-button

  // .fl-button--success

  

  @include m(success){

    // 方法代码重复率过高?怎么降低代码冗余

    // ---> 创建一个新的治理

    // 1:找相同点,和不同点;

    // 2:不同点用形参传入

    // 3:如果有分支用if语句写

    @include button-variant($--button-success-font-color, $--button-success-background-color, $--button-success-border-color);

  }

  

 @include m(error) {

  @include button-variant($--button-error-font-color, $--button-error-background-color, $--button-error-border-color);

 }

 @include m(danger) {

  @include button-variant($--button-danger-font-color, $--button-danger-background-color, $--button-danger-border-color);

 }

 @include m(info) {

  @include button-variant($--button-info-font-color, $--button-info-background-color, $--button-info-border-color);

 }

 @include m(primary) {

  @include button-variant($--button-primary-font-color, $--button-primary-background-color, $--button-primary-border-color);

 }

// .fl-button--medium  .fl-button--small .fl-button-mini

@include m(medium){

  @include button-size($--button-medium-padding-vertical,$--button-medium-padding-horizontal,$--button-mini-font-size,$--button-mini-border-radius)

}

@include m(small){

  @include button-size($--button-small-padding-vertical,$--button-mini-padding-horizontal,$--button-small-font-size,$--button-medium-border-radius)

  

}

@include m(mini){

 @include button-size($--button-mini-padding-vertical,$--button-mini-padding-horizontal,$--button-mini-font-size,$--button-mini-border-radius)
}
}

utils.scss

// 这里写一下样式工具混入指令,
// 因为在很多组件中 需要禁止选中例如 loading model swiper button 
// 控制页面文字无法选中,禁止鼠标右键
@mixin utils-user-select($value) {
    -moz-user-select: $value;
    -webkit-user-select: $value;
    -ms-user-select: $value;
}
// 清楚浮动

总结:以上是完成button按钮的部分工程,未来会更新所有组件的工程化代码。代码进化的过程
注意:以上需要配置打包工具。打包scss文件即可
或者需要你的组件库支持scss环境。
如果有需要我可以加上每种工具打包scss 的文章
下一篇文章;如何编写button组件

你可能感兴趣的:(css,前端工程化,scss,前端,css)