CSS——网格布局(display: grid)之上篇

news2024/11/15 23:53:50

CSS——网格布局(display: grid)

前面介绍了弹性布局,今天我们介绍一下网格布局。

什么是网格布局

CSS网格布局(CSS Grid Layout)是一种用于创建复杂网页布局的系统,它允许开发者以二维系统行和列)来控制元素的布局。跟 Flexbox 类似,网格布局也是作用于两级的 DOM 结构。设置为 display: grid 的元素成为一个网格容器(grid container)。它的子元素则变成网格元素(grid items)。除此之外,另外四个重要的概念如下图所示。

  • 网格线(grid line)——网格线构成了网格的框架。一条网格线可以水平或垂直,并且位于一行或一列的任意一侧。如果指定了 grid-gap 的话,它就位于网格线上。
  • 网格轨道(grid track)——一个网格轨道是两条相邻网格线之间的空间。网格有水平轨道(行)和垂直轨道(列)。
  • 网格单元(grid cell)——网格上的单个空间,水平和垂直的网格轨道交叉重叠的部分。
  • 网格区域(grid area)——网格上的矩形区域,由一个到多个网格单元组成。该区域位于两条垂直网格线和两条水平网格线之间。
    在这里插入图片描述

如何进行网格布局

设置 display: grid 只是网格布局的第一步,下面我们从 grid-template-columnsgrid-template-rows 属性来逐步深入。

grid-template-columns 与 grid-template-rows 属性

  • grid-template-columns: 1fr 1fr 1fr:“fr”代表分数单位(fraction unit),我们这里可以简单的理解为“在被划分的空间中所占据的份数”,所以,这个效果就是:创建三个等宽的列。当然,我们可以采取其他单位,如:%、px等。这些单位可以混搭使用,如:gird-template-columns: 300px 1fr 2fr,那么就会先创建300px宽的列,剩下的空间再分别分配1/3、2/3的空间给剩余的两列。不同单位的优先级如下:
    • 百分比(%):首先,浏览器会计算出可用空间的百分比部分。在这个例子中,第二列的宽度是容器宽度的90%。
    • 固定单位(px等):然后,浏览器会为以像素为单位的列分配固定的空间。在这个例子中,第四列的宽度是100px。
    • 分数(fr):最后,浏览器会将剩余的空间按照分数单位的比例分配给使用 fr 的列。在这个例子中,第一列和第三列分别占据1份和2份。
      示例:
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        /*  
          创建了四个格子,父元素的背景色为黄色,
          其余的为了设置从#111 --> #eee的渐变,并设置了半透明
    	*/
        .main-container {
          width: 1000px;
          background-color: yellow;
        }
    
        .grid-item:nth-child(1) {
          width: 100px;
          padding: 10px;
          border: 1px solid;
          margin-right: 10px;
        }
    
        .grid-container {
          display: grid;
          grid-template-columns: 1fr 95% 100px 2fr;
          grid-template-rows: 1fr;
        }
    
        .grid-item {
          background-color: #999;
        }
    
        div {
          color: red;
          font-size: 1.5rem;
          font-weight: bold;
        }
      </style>
    </head>
    
    <body>
      <main class="main-container">
        <div class="grid-container">
          <div class="grid-item" style="background-color: rgba(17, 17, 17,.5);">项目1</div>
          <div class="grid-item" style="background-color: rgb(85, 85, 85,.5);">项目2</div>
          <div class="grid-item" style="background-color: rgb(153, 153, 153,.5);">项目3</div>
          <div class="grid-item" style="background-color: rgb(238, 238, 238,.5);">项目4</div>
        </div>
      </main>
    </body>
    
    </html>
    

在这里插入图片描述

可以自己复制代码进行尝试,我们在开发者工具中看到:项目1的宽度为100px,项目2的宽度为950px,项目3的宽度为100px,项目4的宽度为16px。

首先看到确实复合前面的规则,但是在明明在分配 fr单位的盒子的宽度之前,父元素的空间就已经占满了,那它们的宽度是如何来的呢?

这里就要解释了:在父元素宽度超出之后,浏览器也知道没有宽度了,所有就不按照 fr 比例进行分配了,而是按照元素的宽度包括内容、内边距,甚至是外边距)进行分配,比如项目1 指定宽度为 100px,所有分配给他100px,至于项目4 没有指定宽度,其内容只有几个文字,而这些文字的字号是用户代理样式表(浏览器默认加载的css文件,确保了在用户未设置样式时网页的可读性,其优先级低于作者样式表,即我们自己添加的css样式)中的字号——16px,与以往不同的是,这里浏览器会尽量压缩宽度,使文字换行显示min-width,中文为一个汉字的宽度,英文为一个单词的宽度)。如果不做处理的话,这些内容会正常的超出显示(如上图所示)。

grid-template-rows的同理。

网格轨道的创建——repeat()函数

该函数可以用于 CSS Grid 属性 grid-template-columnsgrid-template-rows中。repeat() 函数表示轨道列表的重复片段,允许以更紧凑的形式写入大量显示重复模式的列或行。如:grid-template-rows: repeat(3, 2fr 1fr):重复“2fr 1fr”这两个模式三次,总共创建6行。
repeat()函数有两个参数:
第一个参数可以是以下三种之一:

  • 数字(比如1,2,3)
  • auto-fit关键字
  • auto-fill关键字

第二个参数可选值包括:

  • 长度值,可使用单位包括fr、px、em、%和ch等等
  • min-content关键字
  • max-content关键字
  • auto关键字
  • minmax()函数,其可以嵌套min()或者max()函数
  • fit-content()函数
  • 命名线
参数取值
  1. <length>
    正整数数值

  2. <percentage>
    百分比长度。

    • 如果是行(rows),则相对于网格容器的宽度,如果是列(columns),则相对于网格容器的高度。
    • 如果网格容器的大小取决于网格元素,那么必须为关键字 auto
    • 如果网格元素的大小超过了网格容器的大小,那么浏览器会对网格元素的大小进行调整
  3. <flex>
    带有 fr 单位的非负尺寸指定轨道的弹性系数。任何被 <flex> 指定大小的轨道会根据其弹性系数按比例分配剩余空间。

  4. 关键字max-content
    首先介绍一下,min-content和max-content尺寸是根据内容来的,min-content是最小内容尺寸,中文的最小内容单位是一个汉字,英文的最小内容单位是单词,因此min-content最终宽度是所有这些最小内容单元最长的那个单元宽度;max-content是最大内容宽度,可以理解为文本内容不换行时候的宽度。不过,min-content和max-content在实际开发的时候是不会相对于字符进行尺寸设定的,而是相对于图片或者内联性质的容器元素,比方说容器宽度不确定同时一行最多显示一个容器(min-content),或者所有元素在一行显示(max-content)。

    container{
      grid-template-columns: repeat(3, min-content);
    }
    

    min-content 关键字可将轨道设置为与其最小内容一样宽或一样高。通常是单词间没有额外空间时的尺寸。如下图:
    在这里插入图片描述

  5. 关键字min-content
    max-content 关键字的作用基本上与 min-content 相反:它根据网格单元格中最大的内容来确定轨道大小。如下图:
    在这里插入图片描述

  6. 关键字auto
    auto 关键字的最大值为 max-content,最小值为 min-content(auto 只有在与其他值混合时才会出现上述行为。如果单独使用 repeat(3, auto),其行为就像我们设置 repeat(3, 1fr) 一样)。

    .container{
      grid-template-columns: repeat(3, auto 1fr);
    }
    

    在这里,我们将有六列,每一奇数列的宽度设置为 auto。在下面的演示中,我们可以看到,在有足够空间的情况下,带有"auto"文本的 div 将在max-content时达到最大宽度,而 1fr div 则共享剩余空间。当浏览器变窄时,"auto"列继续变窄,直到达到min-content阈值。
    在这里插入图片描述

  7. 关键字auto-fill

    .container {
        grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    }
    

    效果如下,默认宽度很宽的情况下,最后会有匿名的格子:
    在这里插入图片描述
    随着尺寸变小,列数会跟着动态变化,同时宽度自动填充Grid容器(因为设置了1fr)。弹性变化效果如图:
    在这里插入图片描述
    当我们使用auto-fill自动填充的时候,repeat()函数是不能和auto一起使用的,例如下面这种写法是无效的:

    .container {
        /* 无效 */
        grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) auto;
    }
    

    但是可以和长度只和百分比值一起使用,例如:

    .container {
        /* 有效,最后一列的宽度始终为 20% */
        grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) 20%;
    }
    
  8. 关键字auto-fit
    auto-fit 与 auto-fill 的行为是相似的,区别在于auto-fit 会把空的匿名格子进行折叠合并,而这个合并的 0px 大小格子可以认为具有单个格子轨道大小调整的功能,对了,其两侧的格子过道也会合并。在 auto-fill 自动填充的时候,如果 Grid容器的尺寸特别的宽,则最后会有一些空的格子占位:
    在这里插入图片描述但是auto-fit自动适应的时候,如果Grid容器的尺寸特别的宽,则最后会有一些空的格子会合并成 1个,且宽度是 0。auto-fit 区别示意:
    在这里插入图片描述

  9. maxmin()函数
    minmax() 函数本身需要两个参数–最小值和最大值,中间用逗号隔开。因此,通过 minmax(),我们可以在灵活的环境中为轨道设置一系列可能的尺寸。
    例如,我们可以将一列设置为 minmax(40px, 100px),这意味着其最小宽度为 40px,最大宽度为 100px。minmax() 的两个参数都可以使用长度值,如 fr、px、em、% 和 ch,以及 min-content、max-content 和 auto。不过,最好至少为一个参数使用长度值,因为关键字不应该同时作为两个参数工作 。
    下面代码设置了五列,每一列的最小宽度为60px,最大宽度为1fr:

    article {
      grid-template-columns: repeat(5, minmax(60px, 1fr));
    }
    

    minmax() 函数的参数也可以是 min() 或 max() 函数。这两个函数都接收两个参数。min()函数应用两个值中较小的值,而 max() 函数应用较大的值。这在响应式环境中非常有用。

    比如说:

    article {
      grid-template-columns: repeat(5, minmax(min(60px, 8vw), 1fr));
    }
    

    在这里插入图片描述
    上面的代码设置了五列。在宽屏幕浏览器上,五列的间距均为 1fr。在较窄的设备上,列会越来越窄。一旦达到 60px 和 8vw 之间的较低值,就会停止缩小。

  10. fit-content()函数
    只有一个参数,只能为长度或者百分值<length> | <percentage>。
    其底层原理不过多解释,效果可以描述为:“尺寸由内容决定,内容越多尺寸越大,最小为 min-content,最大不超过限定的尺寸”。

    .container {
        grid-template-columns: repeat(2, fit-content(100px) 40px) auto;
    }
    

    在这里插入图片描述

网格元素的安放

三种语法:带编号的网格线命名的网格线以及命名的网格区域

带编号的网格线

网格线编号从左上角为 1 开始递增,负数则指向从右下角开始的位置,如下图:
网格线编号从左上角为 1 开始递增,负数则指向从右下角开始的位置

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>网格布局</title>
  <style>
    .grid-container {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      grid-template-rows: repeat(4, 1fr);
      grid-gap: 10px;
    }

    .header {
      grid-column: 1 / 3;
      grid-row: 1 / 2;
    }

    .nav {
      grid-column: 1 / 3;
      grid-row: 2 / 3;
    }

    .main {
      grid-column: 1 / 2;
      grid-row: 3 / 5;
    }

    .sidebar-top {
      grid-column: 2 / 3;
      grid-row: 3 / 4;
    }

    .sidebar-bottom {
      grid-column: 2 / 3;
      grid-row: 4 / 5;
    }

    .grid-container>div {
      background-color: #999;
    }
  </style>
</head>

<body>
  <div class="grid-container">
    <div class="header">Header</div>
    <div class="nav">Nav</div>
    <div class="main">Main</div>
    <div class="sidebar-top">Sidebar Top</div>
    <div class="sidebar-bottom">Sidebar Bottom</div>
  </div>
</body>

</html>

其中,grid-column 属性是 grid-column-startgrid-column-end 的简写,中间使用 “/” 分隔开。
效果如下:
在这里插入图片描述

span关键字

作为 grid-columngrid-row属性的值,后面跟正整数,表示在前面属性的方向上占据多少个轨道。由于没有指定是具体的哪几行和哪几列,会根据浏览器的布局算法进行布局(这里先不解释)。
以下表示占据两列一行:

.item {
  grid-column: span 2;
  grid-row: span 1;
}
命名的网格线

与前面的带编号的命名方式相似,只不过是为那些编号起了名字(就好像学号和姓名一样,虽然有点“倒反天罡”了,但是大致是这样的意思),不过不必要给所有的网格线都起名字,就相当于并不是所有的人都是学生。结合下面的例子:

 .container {
 display: grid;
 grid-template-columns: [left-start] 2fr
						[left-end right-start] 1fr
						[right-end];
 grid-template-rows: repeat(4, [row] auto);
 grid-gap: 1.5em;
 max-width: 1080px;
 margin: 0 auto;
} 
header,
nav {
 grid-column: left-start / right-end;
 grid-row: span 1;
} 
.main {
 grid-column: left;
 grid-row: row 3 / span 2;
} 
.sidebar-top {
 grid-column: right;
 grid-row: 3 / 4;
} 
.sidebar-bottom {
 grid-column: right;
 grid-row: 4 / 5;
}

在这里插入图片描述

我们把纵向的1、2、3号网格线分别命名为 left-start、left-end(right-start)、right-end,这样我们就可以使用 left-start、left-end(right-start)、right-end代替前面的数字,其语义化更好。
这里有个彩蛋:-start-end 后缀作为关键字,定义了两者之间的区域。如果给元素设置 grid-column: left,它就会跨越从 left-start 到 left-end 的区域
此外,我们还在 repeat()函数中使用了这种写法,由于repeat()函数是用来创建轨道的,我们这里 grid-template-rows: repeat(4, [row] auto)auto 的前面添加 [row]就是在为轨道的前面的网格线起名字,所以导致了最后一根网格线是没有名字的,只有编号 “5”。还注意到 grid-row: row 3 / span 2的操作,虽然我们设置了四条名字一样的网格线,但是我们可以通过“名字 第几条同名线”的组合来定位具体是哪根线。

命名网格区域

不用计算或者命名网格线,直接用命名的网格区域将元素定位到网格中。实现这一方法需要借助网格容器的 grid-template-areas 属性和网格元素的 grid-area 属性。

.container { 
 display: grid; 
 grid-template-areas: "title title"
				      "nav nav" 
					  "main aside1" 
					  "main aside2"; 
 grid-template-columns: 2fr 1fr;
 grid-template-rows: repeat(4, auto);
 grid-gap: 1.5em; 
 max-width: 1080px; 
 margin: 0 auto; 
} 
header { 
 grid-area: title;
} 
nav { 
 grid-area: nav; 
} 
.main { 
 grid-area: main; 
} 
.sidebar-top { 
 grid-area: aside1; 
} 
.sidebar-bottom { 
 grid-area: aside2;
}

grid-template-areas 属性使用了一种 ASCII art 的语法,可以直接在 CSS 中画一个可视化的网格形象。该声明给出了一系列加引号字符串,每一个字符串代表网格的一行,字符串内用空格区分每一列。在这个例子中,第一行完全分配给了网格区域 title,第二行则分配给了 nav。接下来两行的左列分配给了 main,侧边栏的板块分别分配给了 aside1 和 aside2。用 grid-area 属性将每个网格元素放在这些命名区域中。
注意:每个命名的网格区域必须组成一个矩形。不能创造更复杂的形状,比如 L或者 U型。
还可以用句点(.)作为名称,这样便能空出一个网格单元。比如,以下代码定义了四个网
格区域,中间围绕着一个空的网格单元。

grid-template-areas: "top top right"
					 "left . right"
					 "left bottom bottom";

结语

这篇文章已经介绍完网格布局的最基础的部分,也请关注下一篇(实战篇)。感谢大家的支持,如有错误,恳请指出,希望与大家共同进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2141690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++学习】 IO 流揭秘:高效数据读写的最佳实践

✨ 今朝有酒今朝醉&#xff0c;明日愁来明日愁 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3f…

Docker部署ddns-go教程(包含完整的配置过程)

本章教程教程,主要介绍如何用Docker部署ddns-go。 一、拉取容器 docker pull jeessy/ddns-go:v6.7.0二、运行容器 docker run -d \--name ddns-go \--restart unless-stopped \

蓝桥杯—STM32G431RBT6按键的多方式使用(包含软件消抖方法精讲)从原理层面到实际应用(一)

新建工程教程见http://t.csdnimg.cn/JySLg 点亮LED教程见http://t.csdnimg.cn/Urlj5 末尾含所有代码 目录 按键原理图 一、按键使用需要解决的问题 1.抖动 1.什么是抖动 2.抖动类型 3.如何去消除抖动 FIRST.延时函数消抖&#xff08;缺点&#xff1a;浪费CPU资源&#xff…

1.使用 IDEA 过程中的英语积累 - File 菜单(每一次重点积累 5 个单词)

前言 学习可以不局限于传统的书籍和课堂&#xff0c;各种生活的元素也都可以做为我们的学习对象&#xff0c;本文将利用 IDEA 页面上的各种英文元素来做英语的积累&#xff0c;如此做有 3 大利 这些软件在我们工作中是时时刻刻接触的&#xff0c;借此做英语积累再合适不过&…

web开发 之 HTML、CSS、JavaScript、以及JavaScript的高级框架Vue(学习版2)

一、前言 接下来就是来解决这些问题 二、 Ajax 1.ajax javscript是网页三剑客之一&#xff0c;空用来控制网页的行为的 xml是一种标记语言&#xff0c;是用来存储数据的 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-…

Fastjson反序列化漏洞——JNDI注入

一.前言 之前使用反序列化和序列化时写入的到文件里面的&#xff0c;真实环境中&#xff0c;也是这样吗&#xff1f; 当然不是了&#xff0c;通过二进制&#xff0c;字节流数据进行的。 为什么会有JNDI&#xff1f; 由于http和ftp传输消耗资源仍然很大&#xff0c;就有了JRM…

macOS Sequoia发布:Apple又给我们带来了什么惊喜?

今天是个激动人心的日子,尤其是对于Mac用户来说,因为Apple正式发布了全新的操作系统——macOS Sequoia。作为一款专为Mac设备设计的操作系统,Sequoia不仅仅是简单的升级,它承载了Apple在系统体验上的巨大飞跃。听到这个消息,你可能会好奇,Apple这次又会带来什么样的创新?…

【Python】高效图像处理库:pyvips

月亮慢慢变圆&#xff0c;日子慢慢变甜。 在图像处理领域&#xff0c;pyvips 是一个轻量级且高效的库&#xff0c;适合处理大规模图像、实现高性能的操作。相较于其他常见的图像处理库如 PIL 或 OpenCV&#xff0c;pyvips 以其低内存占用和出色的速度脱颖而出。本文将介绍 pyv…

2024年全国大学生数学建模竞赛B题生产过程中的决策问题分析

目录 引言 问题 1&#xff1a;抽样检测方案设计 问题 2&#xff1a;生产过程中的决策 决策阶段划分 决策方案 结果 问题 3&#xff1a;多道工序和零配件的决策 生产流程 决策过程 问题 4&#xff1a;基于抽样检测的重新决策 动态调整次品率 结论 引言 在2024年全国…

[Golang] Sync

[Golang] Sync 文章目录 [Golang] Syncsync.WaitGroupsync.Once对比init() sync.Lock互斥锁和读写锁互斥锁读写锁 死锁问题加锁解锁不成对循环等待 sync.Mapsync/atomicatomic和mutex的区别atomic.value sync.Pool如何使用sync.Pool使用场景 Golang中我们一般提倡使用通信来共享…

Java入门,初识Java

Java背景知识 Java是早期美国 sun 公司&#xff08;Stanford University Network&#xff09;在1995年推出的一门计算机高级编程语言。Java早期称为Oak&#xff08;中文翻译为&#xff1a;橡树&#xff09;&#xff0c;后期改名为Java。&#xff08;因为当时sun公司门口有很多…

MySQL_数据类型简介

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

【计算机网络】TCP 协议——详解三次握手与四次挥手

文章目录 一、引言二、TCP1、TCP 的数据格式2、TCP 的三次握手3、TCP 的四次挥手4、TCP 的全双工通信 三、TCP 的状态转换1、TCP 连接的建立&#xff08;三次握手&#xff09;状态2、TCP 连接的终止&#xff08;四次挥手&#xff09;状态3、TCP 异常情况 一、引言 TCP与UDP的区…

Linux操作系统文件权限管理

Linux操作系统下文件的权限分为当前用户权限、用户组权限和其他用户权限&#xff0c;然后每一类用户或组又分为读权限(r)、写权限(w)和可执行权限(x)。 如图1&#xff0c;打开任一目录&#xff0c;右键单击文件&#xff0c;在弹出菜单选择“属性”&#xff0c;在弹出的属性选项…

一款强大的吉他乐谱编辑软件GuitarPro 8.2中文解锁版

GuitarPro 8.2中文解锁版是一款强大的吉他乐谱编辑软件&#xff0c;适合新手和专业乐手。它提供详尽教程和实用工具&#xff0c;助力初学者掌握吉他技巧&#xff1b;对于专业乐手&#xff0c;它精准记录音符和节奏&#xff0c;提供丰富编辑功能和音效处理。此外&#xff0c;软件…

【python版】示波器输出的csv文件(时间与电压数据)如何转换为频率与幅值【方法④】

将示波器输出的 CSV 文件中的时间和电压数据转换为频率和幅值数据的过程涉及几个步骤&#xff0c;下面是详细的步骤和相关的计算公式&#xff1a; 1. 导入数据 首先&#xff0c;你需要将 CSV 文件中的时间和电压数据导入到数据分析工具中&#xff0c;比如 Python&#xff08;…

【网络】TCP/IP 五层网络模型:网络层

最核心的就是 IP 协议&#xff0c;是一个相当复杂的协议 TCP 详细展开讲解&#xff0c;是因为 TCP 确实在开发中非常关键&#xff0c;经常用到&#xff0c;IP 则不同&#xff0c;和普通程序猿联系比较浅。和专门开发网络的程序猿联系比较紧密&#xff08;开发路由器&#xff0…

深度学习自编码器 - 随机编码器和解码器篇

序言 在深度学习领域&#xff0c;自编码器作为一种无监督学习技术&#xff0c;凭借其强大的特征表示能力&#xff0c;在数据压缩、去噪、异常检测及生成模型等多个方面展现出独特魅力。其中&#xff0c;随机编码器和解码器作为自编码器的一种创新形式&#xff0c;进一步拓宽了…

COTERRORSET—— LLM训练新基准让模型从自身错误中学习

概述 论文地址&#xff1a;https://arxiv.org/pdf/2403.20046.pdf 在最近的研究中&#xff0c;大规模语言模型因其推理能力而备受关注。这些模型在各种任务和应用中取得了令人瞩目的成果&#xff0c;尤其是使用思维链&#xff08;CoT&#xff09;提示方法的有效性已得到证实。…

智慧宿舍平台|基于Springboot+vue的智慧宿舍系统(源码+数据库+文档)

智慧宿舍系统 目录 基于Springbootvue的智慧宿舍系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xff0c;阿里云开发社区乘风者…