在前端开发中,组织和管理 CSS 样式是一个常见的挑战。BEM(Block Element Modifier)架构作为一种解决方案,通过一种清晰且易于维护的方式来组织样式代码。它将样式分解为独立的块(Blocks)、元素(Elements)和修饰符(Modifiers),为团队合作和大型项目提供了一致性和可扩展性。然而,随着项目规模的增长和需求的变化,我们需要更灵活和高效的方式来管理样式,这就引入了 Sass(Syntactically Awesome Stylesheets)。Sass 是一种 CSS 预处理器,它为我们提供了许多强大的工具,如变量、嵌套、混合、继承等,使我们能够更加高效地编写和组织 CSS 代码。本文将深入探讨 BEM 架构的原理及其在实际项目中的应用,并结合 Sass 的强大功能,展示如何通过 Sass 实现 BEM 架构,从而使我们的样式代码更具可维护性、可扩展性和重用性。
1.BEM架构概念
Block(块):Block 是一个独立的、可复用的组件或模块,它代表一个完整的功能单元。块是一个顶层的元素,它本身应该有意义并且可以独立存在。
Element(元素):Element 是块的组成部分,它不能单独存在,必须依赖于块。Element 是块的一部分,它只有在块的上下文中才有意义。
Modifier(修饰符):Modifier 是用于改变块或元素外观、状态或行为的标志。通过添加修饰符类名,可以修改块或元素的样式,从而实现不同的变体。
下面以 Element 组件库为例,感受 BEM 架构的用法与规范:

其中 el-tag 代表一个完整的功能单元块,是一个顶层的元素。
el-tag–primary 表示一个修饰符类,primary 代表样式类型。
el-tag__content 表示的是功能单元块下面的一个子类。
由此,BEM 架构约定的命名规范一般为:namespace-block__element–modifier
2.Sass相关
要使用 Sass 来实现 BEM 架构,首先要先对 Sass 的常见语法以及功能有一定的了解。主要涉及有 Sass 的嵌套规则、父选择器、变量、插值语法、混合等。
实现代码如下:
// src/assets/styles/common.scss
// !default 表示这个变量如果没有赋过别的值,默认为 mx(element中为el,可以更换为自己特有的前缀)
$namespace: 'mx' !default; // 创建一个命名空间,用于定义规范类名的开头
$block-sel: '-' !default; // 创建一个连接,用于连接块名
$element-sel: '__' !default; // 创建一个连接,用于连接元素名
$modify-sel: '--' !default; // 创建一个连接,用于连接标识名
// 创建一个定义 b 的混入,可以生成例如 .mx-bn 的样式
@mixin b($bn) {
$name: $namespace + $block-sel + $bn;
.#{$name} { // 插值语法 即 name 的值
@content; // 相当于一个占位符
}
}
// 创建一个定义 e 的混入,可以生成例如 .mx-bn__en 的样式
@mixin e($en) {
$parent: &; // 获取父级的类名 这里获取的是 .mx-bn
// @at-root 可以让以下类名的样式跳出父级包裹,例如 .mx-bn .mx-bn__en{} 去除多余的父级选择器变为 .mx-bn__en{}
@at-root {
#{$parent + $element-sel + $en} {
@content;
}
}
}
// 创建一个定义 m 的混入,可以生成例如 .mx-bn--mn 的样式
@mixin m($mn) {
$parent: &;
@at-root {
#{$parent + $modify-sel + $mn} {
@content;
}
}
}
3.Vite相关配置
这里以 Vue3 + Vite 项目为例,要将 common.scss 配置为全局通用样式,需要在 vite.config.ts 或 vite.config.js文件中添加 css 配置选项:
export default defineConfig({
plugins: [vue()],
css:{
preprocessorOptions:{
scss:{
additionalData:`@import "@/assets/styles/common.scss";`
}
}
}
})
4.BEM架构在项目中的使用
<template>
<div class="mx-login">
<p class="mx-login__title">账号登录</p>
<button class="mx-login--blue">登录</button>
</div>
</template>
<script lang="ts" setup>
</script>
<style lang="scss">
@include b(login) { // 对应 mx-login
height: 300px;
width: 500px;
display: flex;
flex-direction: column;
align-items: center;
background-color: #eee;
@include e(title) { // 对应 mx-login__title
font-size: 20px;
font-weight: 600;
}
@include m(blue) { // 对应 mx-login--blue
background-color: blue;
}
}
</style>







文章有(1)条网友点评