Vue学习记录之六(组件实战及BEM框架了解)

一、BEM

BEM是一种前端开发中常用的命名约定,主要用于CSS和HTML的结构化和模块化。BEM是Block、Element、Modifier的缩写。

  • Block(块):独立的功能性页面组件,可以是一个简单的按钮,一个复杂的导航条,或者任何其他独立的UI部分。块的名称是唯一的,且通常是名词,比如menu、button等。
  • Element(元素):块的组成部分,具体表现为块内部的某个部分。元素的命名是在块的名称后加上两个下划线__,然后是元素的名称,比如menu__item、button__icon等。
  • Modifier(修饰符):用于定义块或元素的不同状态或外观。修饰符的命名是在块或元素的名称后加上两个破折号--,然后是修饰符的名称,比如button--large、menu__item--active等。

通过这种命名方式,可以使代码具有更好的可读性和可维护性,并且不同组件之间不会发生命名冲突。例如:

html 复制代码
<div class="menu">
  <ul class="menu__list">
    <li class="menu__item menu__item--active">Home</li>
    <li class="menu__item">About</li>
  </ul>
</div>

在这个例子中:

menu 是块(Block),表示一个菜单。

menu__list 是元素(Element),表示菜单中的列表。

menu__item 是元素(Element),表示列表项。

menu__item - - active 是修饰符(Modifier),表示列表项的活动状态。

使用BEM的好处包括:

可读性强:通过明确的命名规则,代码变得更加容易理解。

可维护性高:模块化的结构使得代码更容易维护和更新。

避免命名冲突:由于每个类名都包含了块的名称,避免了全局命名空间的冲突。

二、sass

(Syntactically Awesome Style Sheets)是CSS的扩展,提供了更强大的功能。使用的时候先进行安装。

shell 复制代码
pnpm i sass

1、变量: 定义变量使用 $变量名

css 复制代码
$primary-color: #3498db;

2、嵌套:

css 复制代码
.nav {
  ul {
    list-style: none;
  }
  li {
    display: inline-block;
  }
}

3、混合(Mixins): 使用@mixin

定义和使用混合宏

定义混合宏(mixin):使用 @mixin 指令来定义一组样式。

包含混合宏(mixin):使用 @include 指令来将这些样式应用到某个选择器中。

css 复制代码
@mixin border-radius($radius) {
  border-radius: $radius;
}
.box {
  @include border-radius(10px);
}

4、继承(Extend):

css 复制代码
.button {
  padding: 10px;
  background: $primary-color;
}

.primary-button {
  @extend .button;
  color: white;
}

5、运算:

css 复制代码
.container {
  width: 100% - 20px;
}

6、条件语句:

css 复制代码
@if $theme == dark {
  background: black;
} @else {
  background: white;
}

7、循环:

css 复制代码
@for $i from 1 to 3 {
  .item-#{$i} {
    width: 100px * $i;
  }
}

8、插值语法

用于动态生成类名、ID或其他属性值,通常通过#{$variable}的方式实现。以下是一些插值语法的常见用法:

css 复制代码
//动态生成类名
$color: red;
.text-#{$color} {
  color: $color;
}
这段代码生成的类名是 .text-red。
--------------------------------------
//动态生成属性值 
$size: 16px;
.box {
  width: #{$size * 2};
}
这段代码生成的样式为 width: 32px;。
---------------------------------------
//与其他字符串结合
$prefix: "btn-";
.#{$prefix}primary {
  background-color: blue;
}
这段代码生成的类名是 .btn-primary。
-------------------------------------------
// 在选择器中使用插值
$state: "active";
.button-#{$state} {
  color: green;
}
这段代码生成的类名是 .button-active。

这些语法使得Sass更加灵活,易于管理和维护样式表。 @content 相当于一个占位符,也可以理解为slot(插槽)

  • #{} 用于插入任何类型的值(如属性、选择器名等),不特定于类。
  • .#{} 主要用于生成类选择器,确保插入的内容以.开头,形成有效的类选择器。
    所以,如果你需要插入的内容是类名,就使用.#{};如果是属性名或者其他类型的选择器,则直接使用#{}。

三、使用

1、在src 目录下建立一个bem.scss 文件。

css 复制代码
$namespcae: 'xm' !default;
$block-sel:"-" !default;
$elem-sel:"__" !default;
$mod-sel:"--" !default;

//1、定义block
@mixin b($block){
    //如 class="xm-block" 即: .xm-block{}
    $B: #{$namespcae + $block-sel + $block};
    //命名完了以后,我们初始化下
    .#{$B}{
        //相当于占位符或者插槽
        @content;
    }
}
//2、定义element  如 .xm-block__inner{}  类型的。
@mixin e($e){
    $selector: &; //&符号读取到父级的类名(它代表‌父选择器),即: .xm-block
    /*
    #{$selector + $elem-sel + $e}{
        @content;
    }
    */
    //但是我们一般希望编译出去不要在增加这么一个父级的类型
    //如 .xm-block .xm-block__inner{},这里需要跳出嵌套,
    // 使用 @at-root进行包裹,然后就变成了独立的.xm-block__inner{}。
    @at-root{
        #{$selector + $elem-sel + $e}{
            @content;
        }
    }
}
//3、modify
@mixin m($m){
    $selector: &; 
    @at-root{
        #{$selector + $mod-sel + $m}{
            @content;
        }
    }
}

2、写完规则,要在全局使用,还需要进行配置。 在vite.config.ts 中进行配置。

ts 复制代码
css:{
    preprocessorOptions:{
      scss:{
        additionalData:`@import "./src/deom.scss";`
      }
    }
  }

3、配置完了以后就可以使用了。在App.vue中使用

注意 结构,以块为单位,块内的元素,和修饰符要写在自己的块内。

ts 复制代码
<template>
    <div>
      <div class="xm-test">
        我是块
        <div class="xm-test__inner">我是元素</div>
        <div class="xm-test--success">我是修饰符</div>
      </div>
    </div>
</template>
<script setup lang='ts'>
import A from './components/A.vue';
</script>
<style lang="scss">
@include b(test){
  color: red;
  @include e(inner){
    color: green;
  }
  @include m(success){
    color: orangered;
  }
}
</style>

如果不使用@at-root包裹,那么编译以后就会变成下面的格式:

四、实战

一、使用vite+vue3 构成程序框架。

二、清除默认样式

在根目录下的index.html中加入

html 复制代码
<style>
      *{
        padding: 0;
        margin: 0;
      }
      html,body{
        height: 100%;
        overflow: hidden;
      }

在我们的scss文件中在加入一个混合项:bfc

css 复制代码
$namespcae: 'xm' !default;
$block-sel:"-" !default;
$elem-sel:"__" !default;
$mod-sel:"--" !default;

@mixin bfc{
    height: 100%;
    overflow: hidden;
}

@mixin b($block){
    $B: #{$namespcae + $block-sel + $block};
    .#{$B}{
        @content;
    }
}
@mixin e($e){
    $selector: &; 
    @at-root{
        #{$selector + $elem-sel + $e}{
            @content;
        }
    }
}
@mixin m($m){
    $selector: &; 
    @at-root{
        #{$selector + $mod-sel + $m}{
            @content;
        }
    }
}

然后app.vue 的style中加入:

css 复制代码
<style lang="scss">
  #app{
    @include bfc;
  }
</style>

新增目录结构

Layout/index.vue 代码如下:

ts 复制代码
<template>
    <div class="xm-box">
        <div><Menu></Menu></div>
        <div class="xm-box__right">
            <Header></Header>
            <Content></Content>
        </div>
    </div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
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  //左右拉满,也就是100%显示
    }
}
</style>

Layout/Content/index.vue 代码如下:

ts 复制代码
<template>
    <div class="xm-content">
        <div class="xm-content__items" v-for="item in 100">{{ item }}</div>
    </div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
</script>
<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>

Layout/Header/index.vue 代码如下:

ts 复制代码
<template>
    <div class="xm-header">Header</div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
</script>
<style scoped lang="scss">
@include b(header){
    height:50px;
    border-bottom: 1px solid #ccc;
}
</style>

Layout/Menu/index.vue 代码如下:

ts 复制代码
<template>
    <div class="xm-menu">Menu</div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
</script>
<style scoped lang="scss">
@include b(menu){
    height: 100%;
    min-width: 200px;
    border-right: 1px solid #ccc;
}
</style>
相关推荐
萌萌哒草头将军4 小时前
🚀🚀🚀Prisma 发布无 Rust 引擎预览版,安装和使用更轻量;支持任何 ORM 连接引擎;支持自动备份...
前端·javascript·vue.js
Chef_Chen4 小时前
从0开始学习R语言--Day18--分类变量关联性检验
学习
键盘敲没电4 小时前
【IOS】GCD学习
学习·ios·objective-c·xcode
海的诗篇_5 小时前
前端开发面试题总结-JavaScript篇(一)
开发语言·前端·javascript·学习·面试
AgilityBaby5 小时前
UE5 2D角色PaperZD插件动画状态机学习笔记
笔记·学习·ue5
AgilityBaby5 小时前
UE5 创建2D角色帧动画学习笔记
笔记·学习·ue5
武昌库里写JAVA6 小时前
iview Switch Tabs TabPane 使用提示Maximum call stack size exceeded堆栈溢出
java·开发语言·spring boot·学习·课程设计
ai产品老杨7 小时前
减少交通拥堵、提高效率、改善交通安全的智慧交通开源了。
前端·vue.js·算法·ecmascript·音视频
一弓虽7 小时前
git 学习
git·学习
张老爷子8 小时前
记录uniapp开发安卓使用webRTC实现语音推送
vue.js