element源码解析-样式

作为这样一个庞大的组件库,样式是如何管理的呢?

首先element的样式全都放在了 theme-chalk 文件夹里,与组件一起放在了packages里。
element使用sass管理样式

总目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|-- theme-chalk
|-- src
|-- common //
|-- date-picker //
|-- fonts // icon相关
|-- mixins // 混入,公用代码文件夹
|-- _function.scss
|-- config.scss
|-- function.scss
|-- utils.scss
|-- mixins.scss
|-- index.scss // 各个组件样式汇总文件
|-- alert.scss // 弹框组件样式
|-- ... // 其他组件样式

|-- package.json
|-- components.json // 组件列表(所有组件)文件
|-- README.md // 项目说明文件
|--gulpfiles.js // 构建样式生成css文件

mixins详解

config.scss

定义一些原始值

1
2
3
4
$namespace: 'el';   //  命名空间
$element-separator: '__'; // 元素分隔符
$modifier-separator: '--'; // 修饰符分隔符
$state-prefix: 'is-'; // 状态标识前缀

function。scss

定义一些函数

mixins.scss

bem命名规范
B(代表块)__E(代表元素)–M(代表修饰符)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@import "function";
@import "../common/var";

/* Break-points
-------------------------- */
@mixin res($key, $map: $--breakpoints) {
// 循环断点Map,如果存在则返回
@if map-has-key($map, $key) {
@media only screen and #{inspect(map-get($map, $key))} {
@content;
}
} @else {
@warn "Undefeined points: `#{$map}`";
}
}

/* Scrollbar
-------------------------- */
@mixin scroll-bar {
$--scrollbar-thumb-background: #b4bccc;
$--scrollbar-track-background: #fff;

&::-webkit-scrollbar {
z-index: 11;
width: 6px;

&:horizontal {
height: 6px;
}

&-thumb {
border-radius: 5px;
width: 6px;
background: $--scrollbar-thumb-background;
}

&-corner {
background: $--scrollbar-track-background;
}

&-track {
background: $--scrollbar-track-background;

&-piece {
background: $--scrollbar-track-background;
width: 6px;
}
}
}
}

/* Placeholder
-------------------------- */
@mixin placeholder {
&::-webkit-input-placeholder {
@content
}

&::-moz-placeholder {
@content
}

&:-ms-input-placeholder {
@content
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* BEM
-------------------------- */
/*添加命名空间*/

@mixin b($block) {
$B: $namespace+'-'+$block !global;

.#{$B} {
@content;
}
}
/*
$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
$currentSelector: #{.el-alert__content,};
hitAllSpecialNestRule 判断父级选择器是否包含'--','is',':'
*/
@mixin e($element) {
$E: $element !global;
$selector: &;
$currentSelector: "";
@each $unit in $element {
$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
}

@if hitAllSpecialNestRule($selector) {
@at-root {
#{$selector} {
#{$currentSelector} {
@content;
}
}
}
} @else {
@at-root {
#{$currentSelector} {
@content;
}
}
}
}
/*
修饰符
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
$currentSelector: #{&--success,};
*/
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
}

@at-root {
#{$currentSelector} {
@content;
}
}
}

@mixin configurable-m($modifier, $E-flag: false) {
$selector: &;
$interpolation: '';

@if $E-flag {
$interpolation: $element-separator + $E-flag;
}

@at-root {
#{$selector} {
.#{$B+$interpolation+$modifier-separator+$modifier} {
@content;
}
}
}
}

@mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B) {
$modifierCombo: '';

@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}

@at-root {
#{&}#{$specSelector}.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}

@mixin meb($modifier: false, $element: $E, $block: $B) {
$selector: &;
$modifierCombo: '';

@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}

@at-root {
#{$selector} {
.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}
}
/*
添加 is- 修饰符*/
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}

@mixin extend-rule($name) {
@extend #{'%shared-'+$name};
}

@mixin share-rule($name) {
$rule-name: '%shared-'+$name;

@at-root #{$rule-name} {
@content
}
}

@mixin pseudo($pseudo) {
@at-root #{&}#{':#{$pseudo}'} {
@content
}
}

element中样式用到的命令

1
2
3
4
5
node build/bin/iconInit.js
"build:theme": "
node build/bin/gen-cssfile &&
gulp build --gulpfile packages/theme-chalk/gulpfile.js && // gulp打包
cp-cli packages/theme-chalk/lib lib/theme-chalk" // 复制到根目录lib下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//  build/bin/iconInit.js
// 生成图标json文件
'use strict';
var postcss = require('postcss');
var fs = require('fs');
var path = require('path');
var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/src/icon.scss'), 'utf8');
var nodes = postcss.parse(fontFile).nodes;
var classList = [];

nodes.forEach((node) => {
var selector = node.selector || '';
var reg = new RegExp(/\.el-icon-([^:]+):before/);
var arr = selector.match(reg);

if (arr && arr[1]) {
classList.push(arr[1]);
}
});

classList.reverse(); // 希望按 css 文件顺序倒序排列

fs.writeFile(path.resolve(__dirname, '../../examples/icon.json'), JSON.stringify(classList), () => {});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//  build/bin/gen-cssfile
// 将组件单独样式汇总生成package/theme-chalk/src/index.scss
var fs = require('fs');
var path = require('path');
var Components = require('../../components.json');
var themes = [
'theme-chalk'
];
Components = Object.keys(Components);
var basepath = path.resolve(__dirname, '../../packages/');

function fileExists(filePath) {
try {
return fs.statSync(filePath).isFile();
} catch (err) {
return false;
}
}
themes.forEach((theme) => {
var isSCSS = theme !== 'theme-default';
var indexContent = isSCSS ? '@import "./base.scss";\n' : '@import "./base.css";\n';
Components.forEach(function(key) {
if (['icon', 'option', 'option-group'].indexOf(key) > -1) return;
var fileName = key + (isSCSS ? '.scss' : '.css');
indexContent += '@import "./' + fileName + '";\n';
var filePath = path.resolve(basepath, theme, 'src', fileName);
if (!fileExists(filePath)) {
fs.writeFileSync(filePath, '', 'utf8');
console.log(theme, ' 创建遗漏的 ', fileName, ' 文件');
}
});
fs.writeFileSync(path.resolve(basepath, theme, 'src', isSCSS ? 'index.scss' : 'index.css'), indexContent);
});