BEM 架构是什么?
BEM
架构是对前端样式命名的规范化,顾名思义,BEM
由 块【block】、元素【element】、修饰符【modifier】组成,其主要作用是方便开发团队对前端项目的样式命名进行统一化处理,加强后期的维护工作。
浅谈 BEM 架构组成
块【block】
块
可以理解为一个作用域标签,附有独立实体的意义,例如我们常常将一个页面的头部命名为 header
、内容命名为 content
等等,这在 BEM
架构中采用 -
横杠来连接,常见的有 ElementUI
中用来代表一个表单块的 el-form
。
元素【element】
元素
可以理解为 块
中的子项,没有独立实体的意义,但有一定的语义,例如我们常常将一个列表项命名为 item
、头部的标题命名为 title
等等,这在 BEM
架构中采用 __
双下划线来连接,常见的有 ElementUI
中用来代表一个表单项的 el-form__item
。
修饰符【modifier】
修饰符
可以理解为 块
或 元素
的一个额外标记,主要用来表示一个特定的外观或行为,例如我们常常用绿色来表示一个成功的提示、黄色来表示一个警告的提示等等,这在 BEM
架构中采用 --
双横杠来连接,常见的有 ElementUI
中用来代表一个成功的按钮 el-button--success
。
开始搭建 BEM 架构
搭建 BEM
架构 分为以下 个步骤:
- 首先安装
sass
插件,然后创建一个bem.scss
的文件用于编写BEM
架构代码:
// bem架构 由 b:block(-)、e:element(__)、m:modifier(--)组成
// 参考elementUI的 块级类名:el-input、元素类名:el-input__inner、标识类名:el-button--success
// !default 表示这个变量如果没有赋过别的值,默认为 common
$namespace: 'common' !default; // 创建一个命名空间,用于定义规范类名的开头
$block-sel: '-' !default; // 创建一个连接,用于连接块名
$element-sel: '__' !default; // 创建一个连接,用于连接元素名
$modify-sel: '--' !default; // 创建一个连接,用于连接标识名
@mixin bfc() {
height: 100%;
overflow: hidden;
}
// 创建一个定义 b 的混入,可以生成例如 .common-block 的样式
@mixin b($bn) {
$name: $namespace + $block-sel + $bn;
.#{$name} {
@content;
}
}
// 创建一个定义 e 的混入,可以生成例如 .common-block__inner 的样式
@mixin e($en) {
// 获取父级的类名 这里获取的是 .common-block
$selector: &;
// @at-root 可以让以下类名的样式跳出父级包裹,例如 .common-block .common-block__inner{} 变成单独一个 .common-block__inner{}
@at-root {
#{$selector + $element-sel + $en} {
@content;
}
}
}
// 创建一个定义 m 的混入,可以生成例如 .common-block--primary 的样式
@mixin m($mn) {
$selector: &;
@at-root {
#{$selector + $modify-sel + $mn} {
@content;
}
}
}
- 在
vite.config.ts
中配置全局引入BEM
架构规范:
PS:这里有使用到 @ 别名引入文件的配置,具体的可以参考我的另一篇文章,这里不再赘述【vue3+vite 配置使用 @ 引入文件】
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
// 设置路径别名
alias: {
'@': resolve(__dirname, './src'),
'*': resolve('')
},
},
// 设置全局使用 bem 架构
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "./src/bem.scss";`
}
}
}
})
- 以
Layout
布局来举例运用BEM
架构:
- /views/Layout/Aside/index.vue
<script setup>
import {} from "vue"
</script>
<template>
<div class="common-aside">
aside
</div>
</template>
<style lang="scss" scoped>
@include b(aside) {
height: 100%;
width: 200px;
border-right: 1px solid red;
}
</style>
- /views/Layout/Header/index.vue
<script setup>
import {} from "vue"
</script>
<template>
<div class="common-header">
Header
</div>
</template>
<style lang="scss" scoped>
@include b(header) {
height: 60px;
border-bottom: 1px solid red;
}
</style>
- /views/Layout/Content/index.vue
<script setup>
import {} from "vue"
</script>
<template>
<div class="common-content">
<div class="common-content__item" v-for="item in 100">{{ item }}</div>
</div>
</template>
<style lang="scss" scoped>
@include b(content) {
flex: 1;
overflow: auto;
padding: 10px 10px 20px 10px;
box-sizing: border-box;
@include e(item) {
height: 40px;
margin: 10px;
padding: 10px;
border: 1px solid #000;
border-radius: 4px;
}
}
</style>
- /views/Layout/index.vue
<script setup lang="ts">
import {} from "vue"
import Aside from '@/views/Layout/Aside/index.vue'
import Header from '@/views/Layout/Header/index.vue'
import Content from '@/views/Layout/Content/index.vue'
</script>
<template>
<div class="common-container">
<div class="common-container__left">
<Aside></Aside>
</div>
<div class="common-container__right">
<Header></Header>
<Content></Content>
</div>
</div>
</template>
<style lang="scss" scoped>
@include b(container) {
@include bfc;
display: flex;
background-color: #e9e9e9;
@include e(right) {
display: flex;
flex-direction: column;
flex: 1;
}
}
</style>
- 实际效果图:
以上是在观看B站【小满】的vue3课程时的学习成果,内容仅供参考,如果有写的不对的地方,欢迎在下方留言,一起在前端开发的道路上共同学习进步。。。