sunnyxujian's blog sunnyxujian's blog
首页
  • JavaScript
  • CSS
  • HTML和浏览器
  • Vue
  • Vue3
  • React
  • 基础知识
  • webpack
  • rollup
  • vite
  • 其他
  • Nodejs
  • 网络
  • TypeScript
  • 架构设计
  • 性能优化
  • 数据结构和算法
  • JavaScript教程 笔记
  • ES6 教程 笔记
  • TypeScript 从零实现 axios
  • Git学习 笔记
  • 渲染器原理
  • TypeScript 笔记
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网站
  • 资源
  • Vue资源
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 友链
  • 关于
GitHub (opens new window)

xujian

劝君惜取少年时。
首页
  • JavaScript
  • CSS
  • HTML和浏览器
  • Vue
  • Vue3
  • React
  • 基础知识
  • webpack
  • rollup
  • vite
  • 其他
  • Nodejs
  • 网络
  • TypeScript
  • 架构设计
  • 性能优化
  • 数据结构和算法
  • JavaScript教程 笔记
  • ES6 教程 笔记
  • TypeScript 从零实现 axios
  • Git学习 笔记
  • 渲染器原理
  • TypeScript 笔记
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网站
  • 资源
  • Vue资源
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 友链
  • 关于
GitHub (opens new window)
  • JavaScript

  • CSS

    • CSS教程和技巧收藏
    • flex布局语法
    • flex布局案例-基础
    • flex布局案例-骰子
    • flex布局案例-圣杯布局
    • flex布局案例-网格布局
    • flex布局案例-输入框布局
    • CSS3之transition过渡
    • CSS3之animation动画
    • 「布局技巧」图片未加载前自动撑开元素高度
    • 文字在一行或两行时超出显示省略号
    • 从box-sizing属性入手,了解盒子模型
    • 水平垂直居中的几种方式-案例
    • 如何根据系统主题自动响应CSS深色模式
    • CSS-function汇总
    • Sass中使用BEM宏的小技巧
      • bem-helper.js
      • bem-mixin.scss
  • HTML和浏览器

  • 前端基础
  • CSS
xujian
2021-04-21

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

# bem-mixin.scss

config.scss

$namespace:'z'; // 修饰命名空间
$state-prefix: 'is-';// 修饰状态
$modifier-separator:'--'; // 修饰类型的
$element-separator: '__'; // 划分空间分隔符
1
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

实际用法:

@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
编辑 (opens new window)
#BEM
上次更新: 2022/05/22, 18:34:11
CSS-function汇总
行内元素和块级元素

← CSS-function汇总 行内元素和块级元素→

最近更新
01
😍Vue3和React都在用的函数式编程,学起来~
02-03
02
链表
11-24
03
基础类型
11-18
更多文章>
Theme by Vdoing | Copyright © 2020-2023 xujian | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式