BEM架构

BEM架构是OOCSS架构(面向对象CSS)的一种实现。

BEM是block(块层)、element(元素层)、modifier(修饰符层)的缩写。

Element+用的就是这种架构。

BEM的命名规范:

1
2
3
4
5
6
7
8
/* 块,一个元素区域 */
.block {}

/* 元素,块内的某元素 */
.block__element {}

/* 修饰符,一些同类元素的区分 */
.block--modifier {}

编写bem架构

全局bem.scss:

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
// !default:变量如果没有赋过别的值,就使用"cheriko"这个默认值
$namespace: "cheriko" !default;
$block-sel: "-" !default;
$elem-sel: "__" !default;
$mod-sel: "--" !default;

@mixin b($block) {
// 拼装类名
$B: #{$namespace + $block-sel + $block};
.#{$B} {
// 会被替换成真正的样式
@content;
}
}

@mixin e($el) {
// 读取父级类名
$selector: &;
// 跳出嵌套
@at-root {
// 拼装类名
#{$selector + $elem-sel + $el} {
@content;
}
}
}

@mixin m($m) {
// 读取父级类名
$selector: &;
// 跳出嵌套
@at-root {
// 拼装类名
#{$selector + $mod-sel + $m} {
@content;
}
}
}

在vite.config.ts中加入配置:

1
2
3
4
5
6
7
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/bem.scss";`
}
}
}

在App.vue中测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1 class="cheriko-test">
1145141919810
<div class="cheriko-test__inner">el</div>
<div class="cheriko-test--success">test</div>
</h1>
</div>
</template>

<style lang="scss">
@include b(test) {
color: red;
@include e(inner) {
color: blue;
}
@include m(success) {
color: green;
}
}
</style>

Layout布局

用BEM架构简单实现Element+的Layout布局。

创建scss全局混入(BEM实现代码见上):

1
2
3
4
@mixin bfc {
height: 100%;
overflow: hidden;
}

App.vue中引入布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div id="app">
<Layout></Layout>
</div>
</template>

<script setup lang="ts">
import Layout from "./Layout/index.vue"
</script>

<style lang="scss">
// scoped:给样式制定一个作用域,让它只在该文件里生效
// App.vue中一般不加scoped

#app {
@include bfc;
}
</style>

该布局的文件路径:

index.vue:

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
<template>
<div class="cheriko-box">
<div><Menu></Menu></div>
<div class="cheriko-box__right">
<Header></Header>
<Content></Content>
</div>
</div>
</template>

<script setup lang="ts">
import Menu from "./Menu/index.vue"
import Header from "./Header/index.vue"
import Content from "./Content/index.vue"
</script>

<style scoped lang="scss">
@include b(box) {
@include bfc;
display: flex;
@include e(right) {
display: flex;
flex-direction: column;
flex: 1;
}
}
</style>

Content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div class="cheriko-content">
<div class="cheriko-content__items" v-for="item in 100" :key="item">
{{ item }}
</div>
</div>
</template>

<style scoped lang="scss">
@include b(content) {
flex: 1;
overflow: auto;
@include e(items) {
padding: 10px;
margin: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
}
</style>

Header:

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<div class="cheriko-header">
Header
</div>
</template>

<style scoped lang="scss">
@include b(header) {
height: 50px;
border-bottom: 1px solid #ccc;
}
</style>

Menu:

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div class="cheriko-menu">
Menu
</div>
</template>

<style scoped lang="scss">
@include b(menu) {
height: 100%;
min-width: 200px;
border-right: 1px solid #ccc;
}
</style>