基于 BEM 规范实现简单的全局 scss

2023-11-03

  • 该文章是在学习 小满vue3 课程的随堂记录
  • 示例均采用 <script setup>,且包含 typescript 的基础用法

前言

  • BEM 是 css 常用的命名规范
  • BEM :block(块)element(元素)modify(修饰符)
  • namespace-block__elementnamespace-block---modify 格式为例(namespace 一般是 ui 库的前缀,如 element-ui 的 el 前缀)
  • scss 的使用请参考 scss中文网

一、创建全局 scss文件

在 src 下新建文件 bem.scss,用到 scss 的一些知识:

  • 父子选择器 直接 嵌套使用
  • 变量声明 $
  • 插值 使用:#{变量名}
  • @mixin 定义混入,@include 使用混入
  • @at-root 跳出嵌套
$namespace: "xm" !default; // 命名空间
$block-sel: "-" !default; // block 用 - 连接
$element-sel: "__" !default; // element 用 __ 连接
$modify-sel: "--" !default; // modify 用 -- 连接。      如 xm-page__button--primary

// 生成 block 的规范类,如 .xm-block{}
@mixin b($block) {
  $B: #{$namespace + $block-sel + $block};
  .#{$B} {
    // 这里类似于 插槽的功能,把对应的样式填进来
    @content;
  }
}

// 生成 element 的规范类,如 .xm-block__inner{}
@mixin e($el) {
  // 首先,要先获取父级的类名,使用 &,对应的就是 .xm-block
  $selector: &;

  // 拼接出来是 .xm-block__inner{}
  // 但编译出来的 会是  .xm-block .xm-block__inner{}
  // #{$selector + $element-sel + $el} {
  //   @content;
  // }

  // 如果不想要父级名称,只需要 .xm-block__inner{},则使用 @at-root
  @at-root {
    #{$selector + $element-sel + $el} {
      @content;
    }
  }
}

// 生成 modify 的规范类,如 .xm-block__inner--primary{}
@mixin m($mod) {
  $selector: &;

  @at-root {
    #{$selector + $modify-sel + $mod} {
      @content;
    }
  }
}

二、配置为全局使用

注意,这里直接在 App.vue 的 style 中引入是会报错的,必须在 vite.config.ts 中配置

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 配置 css
  css: {
    // 配置 预处理器
    preprocessorOptions: {
      // 配置 scss
      scss: {
        // 配置 附加数据
        additionalData: `@import './src/bem.scss';`,
      },
    },
  },
});

三、组件中使用

  • 普通嵌套,编译后会 加上父级前缀
  • 注意 & 的用法,直接使用不会多父级前缀,但使用 bem.scss 这里会多一层,所以 bem.scss中 使用 @at-root 跳出了嵌套
<div class="blue">
    哈哈哈
    <div class="blue-name">笑笑</div>
  </div>
  <div class="xm-test">
    B
    <div class="xm-test__inner">E</div>
    <div class="xm-test--success">M</div>
  </div>
</div>
<style lang="scss" scoped>
// blue-name 这样写编译出来的 是 .blue .blue-name {}
.blue {
  font-size: 30px;
  .blue-name {
    font-size: 40px;
  }
}

// blue-name 这样写编译出来的是 .blue-name {}
.blue {
  font-size: 30px;
  &-name {
    font-size: 40px;
  }
}

// 书写时必须保持对应的嵌套关系,否则无效
@include b(test) {
  color: red;
  font-size: 40px;
  @include e(inner) {
    color: blue;
    font-size: 30px;
  }
  @include m(success) {
    color: green;
    font-size: 16px;
  }
}
</style>

编译结果:

在这里插入图片描述

页面展示:

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于 BEM 规范实现简单的全局 scss 的相关文章