Sass中使用BEM宏的小技巧
BEM是由 Yandex 团队提出的一种 CSS 命名方法论(Block, Element, Modifier)。
BEM 是一个分层系统,它把我们的网站分为三层,这三层正好对应着 BEM 三个英文单词的简写 block, element, modifier。分为 块层、元素层、修饰符层。 它在封装组件时具有明显优势,并且写出来的代码易于维护。最大的特点是与现有 MVVM 框架具有良好的结合,极大的增加了组件的开发效率。
# bem-helper.js
块(block)、元素(element)、修饰符(modifier)
生成符合bem规范的css类名,用法如下:
bem() // 'button'
bem('text') // 'button__text'
bem({ disabled }) // 'button button--disabled'
bem('text', { disabled }) // 'button__text button__text--disabled'
bem(['disabled', 'primary']) // 'button button--disabled button--primary'
const ELEMENT = '__';
const MODS = '--';
const join = (name, el, symbol) => el ? name + symbol + el : name;
// 大驼峰转换中划线
const toMidLine = (name) => name.replace(/([A-Z])/g, '-$1').toLowerCase().substr(1);
const prefix = (name, mods) => {
if (typeof mods === 'string') {
return join(name, mods, MODS);
}
if (Array.isArray(mods)) {
return mods.map(item => prefix(name, item));
}
const ret = {};
Object.keys(mods).forEach(key => {
ret[name + MODS + key] = mods[key];
});
return ret;
};
function bem(el, mods) {
const { name } = this.$options || 'NotNamedComponent';
const block = toMidLine(name)
if (el && typeof el !== 'string') {
mods = el;
el = '';
}
el = join(block, el, ELEMENT);
return mods ? [el, prefix(el, mods)] : el;
}
export default bem;
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
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
# bem-mixin.scss
config.scss
$namespace:'z'; // 修饰命名空间
$state-prefix: 'is-';// 修饰状态
$modifier-separator:'--'; // 修饰类型的
$element-separator: '__'; // 划分空间分隔符
1
2
3
4
2
3
4
mixin.scss
@import "../common/var.scss";
// .z-button{}
@mixin b($block) {
$B: $namespace+'-'+$block;
.#{$B}{
@content;
}
}
// .z-button.is-xxx
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
// &--primary => .z-button--primary
@mixin m($modifier) {
@at-root {
#{&+$modifier-separator+$modifier} {
@content;
}
}
}
// &__header => .z-button__header
@mixin e($element) {
@at-root {
#{&+$element-separator+$element} {
@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
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
实际用法:
@mixin button-variant($color, $background-color, $border-color) {
color: $color;
background: $background-color;
border-color: $border-color;
}
@include b(button) {
// BEM规范
display: inline-block;
cursor: pointer;
@include when(disabled) { // 针对不同类型处理
&,
&:hover,
&:focus {
cursor: not-allowed
}
}
@include when(round) {
border-radius: 20px;
padding: 12px 23px;
}
@include when(loading) {
pointer-events: none;
}
@include m(primary) { //渲染不同类型的button
@include button-variant($--color-white, $--color-primary, $--color-primary)
}
@include m(success) {
@include button-variant($--color-white, $--color-success, $--color-success)
}
@include m(warning) {
@include button-variant($--color-white, $--color-warning, $--color-warning)
}
@include m(danger) {
@include button-variant($--color-white, $--color-danger, $--color-danger)
}
@include m(info) {
@include button-variant($--color-white, $--color-info, $--color-info)
}
}
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
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
编辑 (opens new window)
上次更新: 2022/05/22, 18:34:11