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>
相关推荐
weixin_4554461710 分钟前
Python学习的主要知识框架
开发语言·python·学习
Jiaberrr2 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
Ylucius3 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
200不是二百3 小时前
Vuex详解
前端·javascript·vue.js
LvManBa3 小时前
Vue学习记录之三(ref全家桶)
javascript·vue.js·学习
深情废杨杨4 小时前
前端vue-父传子
前端·javascript·vue.js
知识分享小能手4 小时前
mysql学习教程,从入门到精通,SQL DISTINCT 子句 (16)
大数据·开发语言·sql·学习·mysql·数据分析·数据库开发
工业互联网专业4 小时前
毕业设计选题:基于springboot+vue+uniapp的驾校报名小程序
vue.js·spring boot·小程序·uni-app·毕业设计·源码·课程设计