elementUI组件样式引入源码阅读笔记

前言

主要是在阅读elementUI组件源码时,对其样式的统一封装学习笔记。从中可以学习了解到scss在一个大型项目如何应用以及封装。

目录结构

element的样式存放在element的packages/theme-chalk中,目录结构如下所示:

│  alert.scss //组件样式
│  aside.scss
│  autocomplete.scss
│  avatar.scss
│  backtop.scss
│  badge.scss
│  base.scss
│  breadcrumb-item.scss
│  breadcrumb.scss
│  button-group.scss
│  button.scss
|  // 省略部分组件样式
├─common // 组件共用样式
│      popup.scss //弹层类组件共用样式
│      transition.scss //主要定义了element组件中使用vue的 transition 组件时用到的动态效果样式
│      var.scss // 定义了element各组件UI的基本样式的变量,包括颜色,文本大小,边框大小,组件不同尺寸对应的不同样式
│      
├─date-picker // date组件使用样式
│      date-picker.scss
│      date-range-picker.scss
│      date-table.scss
│      month-table.scss
│      picker-panel.scss
│      picker.scss
│      time-picker.scss
│      time-range-picker.scss
│      time-spinner.scss
│      year-table.scss
│      
├─fonts // 字体文件
│      element-icons.ttf
│      element-icons.woff
│      
└─mixins // scss复用函数
       config.scss // 样式名的全局配置
       function.scss // 组件样式使用到的sccss函数
       mixins.scss // 共用的mixins函数
       utils.scss // 工具类函数样式, 如禁用用户选择
       _button.scss // 按钮基本样式
复制代码

主要文件分析

config.scss

config.scss 文件定义了element样式的全局配置,如样式名前缀,,样式名分割符等

// 这四个样式名配置是element所有样式名定义的基础
// 如: el-button, el-select, is-disabled等样式名
$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';
复制代码

mixins.scss

mixins.scss 文件定义了element各组件样式使用的基本mixins,这里对最主要的mixinx做分析

  1. @mixin b() 混入el
@mixin b($block) {
	// 假如 $block为button
  $B: $namespace+'-'+$block !global;  $namespace在config.scss中定义为el,故$B为el-blutton
  .#{$B} {    // .#{} 为scss变量插值,编译后为.el-button
    @content;
  }
}
// @content`用在mixin里面的,当定义一个mixin后,并且设置了@content
// @include的时候可以传入相应的内容到mixin里面
复制代码
  1. @mixin e() 混入__
@mixin e($element) {
  /**假设$element为disabled **/
  $E: $element !global;
  $selector: &;  // 父选择器
  $currentSelector: ""; // 要生成的选择器
  /** 遍历$element //可能有多个
  /* $B 为 mixin b()混入中的变量名
  /* 这里使用$B是因为在element组件样式中e的混入必定是在b混入下的
  /* 如果是在el-button下使用e混入,则生成 .el-button__disabked
  **/
  @each $unit in $element {
    $currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
  }
  /** hitAllSpecialNestRule 判断$elector是否包含--, is-, 在function.scc 中定义
  /* 这里判断是否包含is--,--是因为使用了 @at-root
  /* @at-root指令可以使一个或多个规则被限定输出在文档的根层级上,而不是被嵌套在其父选择器下
  /* 包含有is--等前缀的样式名,在组件中一般是可移除的,所以在输出在文档的根层级上时要加上父选择器
  **/
  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$currentSelector} {
        @content;
      }
    }
  }
}
复制代码
  1. @mixin m() 混入–
/** 
/* 该方法与混入e基本相同,不同的是没有判断hitAllSpecialNestRule
/* 因为混入 -- 一般的是组件的尺寸样式,如 el-radio--medium,el-radio--small等,父选择器一般为el-radio等,
/* 故不需要判断
**/
@mixin m($modifier) {
  $selector: &;
  $currentSelector: "";
  @each $unit in $modifier {
    $currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
  }

  @at-root {
    #{$currentSelector} {
      @content;
    }
  }
}
复制代码
  1. @mixin w() 混入 is
/** 假设$state为check
/* 则编译后为在文档的根层级(在组件中使用时,为组件根样式)为.el-radio.is-checked
**/
@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}
复制代码

functon.scss

function.scss 主要是定义了 hitAllSpecialNestRule 函数方法,主要用来判断选择器是否含有’is-‘, ‘–‘, ‘:’ 等字符。主要代码如下:

@import "config";

/* BEM support Func
 -------------------------- */
@function selectorToString($selector) {
  //字符化
  $selector: inspect($selector);
  /** str-slice 
  /* 从 $string 中截取子字符串,通过 $start-at 和 $end-at 
  /* 设置始末位置,未指定结束索引值则默认截取到字符串末尾。
  /* 这里主要是去除第一个字符和最后一个字符,避免如 --el, el:等的干扰
  **/
  $selector: str-slice($selector, 2, -2);
  @return $selector;
}

@function containsModifier($selector) {
  $selector: selectorToString($selector);
    /** str-index($string, $substring)
    /* 返回一个下标,标示 $substring 在 $string 中的起始位置。没有找到的话,则返回 null 值。
    /* $modifier-specarator --
  	**/
  @if str-index($selector, $modifier-separator) {
    @return true;
  } @else {
    @return false;
  }
}

@function containWhenFlag($selector) {
  $selector: selectorToString($selector);
/** $state-prefix: 'is-'; **/
  @if str-index($selector, '.' + $state-prefix) {
    @return true
  } @else {
    @return false
  }
}

@function containPseudoClass($selector) {
  $selector: selectorToString($selector);

  @if str-index($selector, ':') {
    @return true
  } @else {
    @return false
  }
}
//** 对上述四种情况进行判断,有一种存在就返回true **/
@function hitAllSpecialNestRule($selector) {

  @return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享