目前有很多公司为了降低人员成本,定制了公司内部组件库。有的公司居于某个组件库二次封装,弊端及时维护升级困难。如果有一套工程化。
大部分公司虽然使用css预处理器,但是也是只写法上与css没什么区别。。。 失去了预处理器真正的作用和价值。
应该向写js脚本一样,能封装就封装,能抽象就抽象
应该从一下几个角度完成样式工程化:
这里我更加建议,应该在一个完整的设计搞前提下,提前定义好规范
学习角度改如何完成规范:
学习案例如下:
例如: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){
}
总结:不论是选择器名字,还是样式体中样式;关键都是找相同点在抽离
.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组件