前言

最近刚开学, 做完了一个学生管理系统, 之前一直在写后端, 前端都没咋学这次一下来一个大总结, 避免之后又忘了😭😭😭( 文章里的示例代码都是黑马程序员的讲义哦 )

这里写目录标题

概述:

1.web前端主要由三部分组成:

  • HTML:负责网页的结构(页面元素和内容)。
  • CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)。
  • JavaScript:负责网页的行为(交互效果)。

2.其中还有前端开发中的高级技术Vue、ElementPlus、Axios需要掌握。

1.HTML入门程序(🙌用一个程序看看HTML是干嘛的)

先来看看实现(一个标题,一个图片(图片是我随便找的)):
在这里插入图片描述
来看看代码:

1.新建文件夹htmlhhhh
在这里插入图片描述

2.打开VS-Code打开文件夹,在文件夹里新建文本文件,后缀名改为 .html,命名为:01. html快速入门.html,新建img文件夹,导入 1.png 文件:

在这里插入图片描述
在01. html快速入门.html写入:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML 快速入门</title>
</head>
<body>
  <h1>Hello HTML</h1>
  <img src="img/1.png">
</body>
</html>

🧩扩展:

  1. 输入一个! (要用英文哦),可以快速生成框架:
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
3. 标题标签 h 系列:

在这里插入图片描述

效果:h1为一级标题,字体也是最大的 ; h6为六级标题,字体是最小的。

总结一下吧✌️,HTML语法:
HTML: HyperText Markup Language,超文本标记语言。

  • 超文本:超越了文本的限制,比普通文本更强大。除了文字信息,还可以定义图片、音频、视频等内容。
  • 标记语言:由标签 “<标签名>” 构成的语言
    HTML代码直接在浏览器中运行,HTML标签由浏览器解析 。

2.CSS入门程序(🙌来看看CSS具体是干嘛的)

先来看看实现吧(新闻发布时间 2024年05月15日 20:07 的字体颜色是灰色的,这个就是用CSS实现的)

在这里插入图片描述

代码:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>【哈哈哈哈哈哈哈】哈哈哈哈哈哈哈哈哈哈哈哈</title>
  <style>
    .publish-date {
      color: gray;
    }
  </style>
</head>
<body>

  <!-- 定义网页标题, 标题内容: 哈哈哈哈哈哈哈 -->

  <h1 id="title">【哈哈哈哈哈哈哈】哈哈哈哈哈哈哈哈哈哈哈哈</h1>


  <!-- 定义一个超链接, 链接地址:https://news.cctv.com/, 链接内容:央视网 -->
  <a href="https://news.cctv.com/" target="_blank">央视网</a>
  <span class="publish-date">2024年05月15日 20:07</span>

</body>
</html>

其实Css就是选择前端一个板块,然后指定样式。选择方式:其实有三种 ,上面是用的最多的一种用CSS选择器,来看看常用的选择器吧:

在这里插入图片描述

前面说了用HTML标签来写和装饰文本,那他是横着排还是竖着排?我们来看看页面的布局

  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>
    
    /* 设置段落首行缩进 */
    p {
      text-indent: 2em; /* 首行缩进2em */
      line-height: 2; /* 行高2倍 */
    }

    /* 新增样式 */
    .news-content {
      width: 70%; /* 宽度占70% */
      margin: 0 auto; /* 横向居中 */
    }
  </style>
</head>
<body>
    <!-- 包裹新闻内容的容器 -->
    <div class="news-content">

      <h1 id="title">【哈哈哈哈哈哈哈】哈哈哈哈哈哈哈哈哈哈哈哈</h1>
      
      <p>
        <strong>hhhhh消息</strong>(hhhh联播): 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈     
      </p>
      <p>
        哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
      </p>

      <p>
        哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
      </p>

      <p>
        哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
      </p>
     
    
      
    </div>
</body>
</html>

总结一下吧:

  • 盒子:页面中所有的元素(标签),都可以看做是一个 盒子,由盒子将页面中的元素包含在一个矩形区域内,通过盒子的视角更方便的进行页面布局。

  • 盒子模型组成:内容区域(content)、内边距区域(padding)、边框区域(border)、外边距区域(margin)。

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>盒子模型</title>
    <style>
        div {
            width: 200px;   /* 内容宽度 */
            height: 200px;  /* 内容高度 */
            box-sizing: border-box; /* 指定width height为盒子的高宽 */
            background-color: aquamarine; /* 背景色 */
            
            padding: 20px 20px 20px 20px; /* 内边距, 上 右 下 左 , 边距都一行, 可以简写: padding: 20px;*/ 
            border: 10px solid red; /* 边框, 宽度 线条类型 颜色 */
            margin: 30px 30px 30px 30px; /* 外边距, 上 右 下 左 , 边距都一行, 可以简写: margin: 30px; */
        }
    </style>
</head>

<body>
        
    <div>
        A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A 
    </div>
    
</body>
</html>

在这里插入图片描述

2.2. flex布局

布局有了盒子模型为什么要有flex呢?✅ 说说他的好处:

  • 它是现代网页布局的基石,90% 的页面都需要它。
  • 它解决了传统布局的痛点:居中难、对齐难、自适应难(只靠 margin/padding 太难了!)。
  • 它简单直观:只要记住“父容器控制布局”,就能快速上手。
  • 它兼容性好:所有现代浏览器都支持。

还是来看看一个例子:
在这里插入图片描述

<!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>
    #container {
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      background-color: #aeea6a;
      width: 400px;
      height: 300px;
    }

    #container div {
      background-color: #e866ef;
      width: 100px;
      height: 50px; 
    }
  </style>
</head>
<body>
  <div id="container">
    <div>Flex Item</div>
    <div>Flex Item</div>
    <div>Flex Item</div>
  </div>
</body>
</html>

来总结一下吧:

flex布局相关的CSS样式:
在这里插入图片描述

主轴(main axis) → → → → → → →

交叉轴(cross axis)

  • 主轴方向:由 flex-direction 决定(默认是 row 横向)。
  • 交叉轴:与主轴垂直的方向。

在这里插入图片描述

如果主轴设置为row,其实就是横向布局。 主轴设置为column,其实就是纵向布局。

在这里插入图片描述

🌏其实HTML还有好多标签,Css也是,我们还可以用它做表格,规定整个页面的布局等等,在这里就不一 一列举了,直接来个实现🤔(作为前面学习内容的应用):

1.首先:来看看实现功能(是一个表格哦,有点像之前苍穹外买的菜品,菜品分类的查询功能):

在这里插入图片描述

2.来看看代码吧:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tlias智能学习辅助系统</title>
    <style>
      body {
        margin: 0;
      }

      /* 顶栏样式 */
      .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          background-color:  #c2c0c0;
          padding: 10px 20px;
          box-shadow: 0 2px 5px rgba(0,0,0,0.1);
      }
      
      /* 加大加粗标题 */
      .header h1 {
          margin: 0;
          font-size: 24px;
          font-weight: bold;
      }

      /* 文本链接样式 */
      .header a {
          text-decoration: none;
          color: #333;
          font-size: 16px;
      }

      /* 搜索表单区域 */
      .search-form {
          display: flex;
          align-items: center;
          padding: 20px;
          background-color: #f9f9f9;
      }

      /* 表单控件样式 */
      .search-form input[type="text"], .search-form select {
          margin-right: 10px;
          padding: 5px 10px;
          border: 1px solid #ccc;
          border-radius: 4px;
          width: 200px;
      }

      /* 按钮样式 */
      .search-form button {
          padding: 5px 15px;
          margin-left: 10px;
          background-color: #007bff;
          color: white;
          border: none;
          border-radius: 4px;
          cursor: pointer;
      }

      /* 清空按钮样式 */
      .search-form button.clear {
        background-color: #6c757d;
      }

      .table {
         min-width: 100%; 
         border-collapse: collapse;
      }

      /* 设置表格单元格边框 */
      .table td, .table th { 
        border: 1px solid #ddd; 
        padding: 8px; 
        text-align: center;
      }
      
      .avatar { 
        width: 30px; 
        height: 30px; 
        object-fit: cover; 
        border-radius: 50%; 
      }

      /* 页脚版权区域 */
    .footer {
        background-color: #c2c0c0;
        color: white;
        text-align: center;
        padding: 10px 0;
        margin-top: 30px;
    }

    .footer .company-name {
        font-size: 1.1em;
        font-weight: bold;
    }

    .footer .copyright {
        font-size: 0.9em;
    }

    #container {
      width: 80%;
      margin: 0 auto;
    }
    </style>
</head>
<body>
    
  <div id="container">
    <!-- 顶栏 -->
    <div class="header">
      <h1>Tlias智能学习辅助系统</h1>
      <a href="#">退出登录</a>
    </div>

    <!-- 搜索表单区域 -->
    <form class="search-form" action="#" method="post">
      <input type="text" name="name" placeholder="姓名" />
      <select name="gender">
          <option value="">性别</option>
          <option value="male"></option>
          <option value="female"></option>
      </select>
      <select name="position">
          <option value="">职位</option>
          <option value="班主任">班主任</option>
          <option value="讲师">讲师</option>
          <option value="学工主管">学工主管</option>
          <option value="教研主管">教研主管</option>
          <option value="咨询师">咨询师</option>
      </select>
      <button type="submit">查询</button>
      <button type="reset" class="clear">清空</button>
    </form>

    <table class="table table-striped table-bordered">
      <thead>
          <tr>
              <th>姓名</th>
              <th>性别</th>
              <th>头像</th>
              <th>职位</th>
              <th>入职日期</th>
              <th>最后操作时间</th>
              <th>操作</th>
          </tr>
      </thead>
      <tbody>
          <tr>
              <td>令狐冲</td>
              <td></td>
              <td><img src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲" class="avatar"></td>
              <td>讲师</td>
              <td>2021-03-15</td>
              <td>2023-07-30T12:00:00Z</td>
              <td class="btn-group">
                  <button>编辑</button>
                  <button>删除</button>
              </td>
          </tr>
          <tr>
              <td>任盈盈</td>
              <td></td>
              <td><img src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈" class="avatar"></td>
              <td>学工主管</td>
              <td>2020-04-10</td>
              <td>2023-07-29T15:00:00Z</td>
              <td class="btn-group">
                  <button>编辑</button>
                  <button>删除</button>
              </td>
          </tr>
          <tr>
              <td>岳不群</td>
              <td></td>
              <td><img src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="岳不群" class="avatar"></td>
              <td>教研主管</td>
              <td>2019-01-01</td>
              <td>2023-07-30T10:00:00Z</td>
              <td class="btn-group">
                  <button>编辑</button>
                  <button>删除</button>
              </td>
          </tr>
          <tr>
              <td>宁中则</td>
              <td></td>
              <td><img src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="宁中则" class="avatar"></td>
              <td>班主任</td>
              <td>2018-06-01</td>
              <td>2023-07-29T09:00:00Z</td>
              <td class="btn-group">
                  <button>编辑</button>
                  <button>删除</button>
              </td>
          </tr>
      </tbody>
    </table>

    <!-- 页脚版权区域 -->
    <footer class="footer">
      <p class="company-name">江苏传智播客教育科技股份有限公司</p>
      <p class="copyright">版权所有 Copyright 2006-2024 All Rights Reserved</p>
    </footer>

  </div>

</body>
</html>

是不是好长好长😨😱,没事之后学的Javascript和Vue,会简化代码的

虽然很长而且以后可能会白雪,但我们还是要看看,解析解析:

  1. 首先来看看HTML标签(功能里用到的):
1. 文档结构标签

<!DOCTYPE html>:定义文档类型为 HTML5。
<html lang="zh-CN">:根元素,声明文档为中文(简体)语言。
<head>:包含文档的元数据(如字符集、标题、样式等)。
<meta>:用于定义字符编码、视口设置等元信息。
charset="UTF-8":指定字符编码为 UTF-8。
name="viewport":用于响应式设计,控制页面在移动设备上的缩放。
<title>:定义网页标题,显示在浏览器标签页上。
<style>:嵌入 CSS 样式代码。
<body>:包含网页的主体内容。

2. 布局与容器标签

<div>:通用块级容器,用于布局和分组内容。
如:.header、#container、.search-form 等。
<footer>:语义化标签,表示页脚区域。

3. 表单与交互标签
<form>:定义表单,用于用户输入和提交数据。
<input type="text">:文本输入框,用于输入姓名。
<select>:下拉选择框,用于选择性别和职位。
<option>:定义下拉列表中的选项。
<button type="submit">:提交按钮,用于提交表单。
<button type="reset">:重置按钮,清空表单内容。

4. 表格标签
<table>:定义表格。
<thead>:表格的头部区域。
<tbody>:表格的主体区域。
<tr>:表格中的行(table row)。
<th>:表头单元格(table header),用于列标题。
<td>:标准单元格(table data),用于表格数据。

5. 文本与链接标签
<h1>:一级标题,用于页面主标题。
<a href="#">:超链接,此处用于“退出登录”功能。
<p>:段落标签,用于页脚中的版权信息。

6. 多媒体标签
<img>:插入图片,用于显示用户头像。
使用 src 指定图片路径,alt 提供替代文本,class 应用样式。

  1. 来看看Css选择器,和修饰表示方式(太多了我让AI干的,有点啰嗦🤪):

👍一、整体结构与布局:

1.body

body {
  margin: 0;
}

作用:清除浏览器默认的外边距(margin),使页面内容紧贴浏览器边缘。
目的:实现更精确的布局控制。

2.#container

#container {
  width: 80%;
  margin: 0 auto;
}

作用:
设置容器宽度为父元素(body)的 80%。
margin: 0 auto 实现水平居中。

目的:让整个页面内容在视口中居中显示,留出左右边距,提升视觉舒适度。

二、头部区域 .header

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #c2c0c0;
  padding: 10px 20px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
  • display: flex:启用弹性布局。
  • justify-content: space-between:两端对齐,标题在左,“退出登录”在右。
  • align-items: center:垂直居中对齐子元素。
  • 背景与阴影:灰色背景 + 轻微下阴影,增强层次感。
  • 内边距:上下 10px,左右 20px,提供呼吸空间。
.header h1 {
  margin: 0;
  font-size: 24px;
  font-weight: bold;
}

.header a {
  text-decoration: none;
  color: #333;
  font-size: 16px;
}
  • 清除标题默认 margin。
  • 链接去除下划线,深灰色文字,可读性强。

三、搜索表单 .search-form

.search-form {
  display: flex;
  align-items: center;
  padding: 20px;
  background-color: #f9f9f9;
}
  • 弹性布局,方便对齐输入框和按钮。
  • 浅灰色背景,与头部和表格形成区分。
  • 内边距提供间距

表单控件样式

.search-form input[type="text"], .search-form select {
  margin-right: 10px;
  padding: 5px 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  width: 200px;
}
  • 统一输入框和下拉框样式。
  • 圆角边框(border-radius)更现代。
  • 固定宽度便于对齐。

按钮样式

.search-form button {
  padding: 5px 15px;
  margin-left: 10px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.search-form button.clear {
  background-color: #6c757d;
}
  • 主按钮为蓝色(Bootstrap 风格),清空按钮为灰色。
  • 去除边框,使用背景色突出。
  • 光标变为指针,提示可点击。

四、表格样式 .table

.table {
  min-width: 100%;     /* 表格最小宽度撑满容器 */
  border-collapse: collapse;  /* 合并边框,消除双线 */
}

单元格通用样式

.table td, .table th {
  border: 1px solid #ddd;     /* 浅灰色边框 */
  padding: 8px;
  text-align: center;         /* 内容居中 */
}
  • 所有单元格居中对齐,视觉整齐。
  • border-collapse: collapse 让表格线条更紧凑美观

五、头像样式 .avatar

.avatar {
  width: 30px;
  height: 30px;
  object-fit: cover;     /* 图像裁剪以填充容器 */
  border-radius: 50%;     /* 圆形头像 */
}
  • 实现圆形头像效果。
  • object-fit: cover 确保图片不变形,居中裁剪。

六、页脚 .footer

.footer {
  background-color: #c2c0c0;
  color: white;
  text-align: center;
  padding: 10px 0;
  margin-top: 30px;
}
  • 与头部同色背景,形成首尾呼应。
  • 白色文字提高对比度。
  • 居中对齐文本。
  • margin-top: 30px 提供与上方内容的间距。

文字样式细分

.footer .company-name {
  font-size: 1.1em;
  font-weight: bold;
}

.footer .copyright {
  font-size: 0.9em;
}

🙌来简单概括一下JavaScript

JavaScript(简称:JS) 是一门跨平台、面向对象的脚本语言,是用来控制网页行为的,实现人机交互效果。JavaScript 和 Java 是完全不同的语言,不论是概念还是设计。但是基础语法类似。

  • 组成:
    • ECMAScript: 规定了JS基础语法核心知识,包括变量、数据类型、流程控制、函数、对象等。
    • BOM:浏览器对象模型,用于操作浏览器本身,如:页面弹窗、地址栏操作、关闭窗口等。
    • DOM:文档对象模型,用于操作HTML文档,如:改变标签内的内容、改变标签内字体样式等。

来看看怎么用?JS引入方式:

js代码也是书写在html中的,那么html中如何引入js代码呢?主要通过下面的2种引入方式:

来看实现:

  1. 内部脚本,将Js代码定义在HTML页面中

在这里插入图片描述

来看看代码:

<!-- 生成文档类型为HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- 字符集 -->
  <meta charset="UTF-8">
  <!-- 设置网页在移动设备上的显示方式 -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-引入方式</title>
</head>
<body>

  <script>
    //内部脚本
    alert('内部脚本');
  </script>
</body>
</html>
  1. 外部脚本, 将JS代码定义在外部 JS文件中,然后引入到 HTML页面中

在这里插入图片描述
在文件中定义Js文件夹,创建demo.js
在这里插入图片描述
写入要操作的弹出框:

alert('javasqp');
<!-- 生成文档类型为HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- 字符集 -->
  <meta charset="UTF-8">
  <!-- 设置网页在移动设备上的显示方式 -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-引入方式</title>
</head>
<body>
  

  <script src="js/demo.js"></script>
</body>
</html>

Js基础语法

1.输出语句:

  • window.alert(…) 警告框
  • document.write(…) 在HTML输出内容
  • console.log(…) 写入浏览器控制台

2.变量/常量
JS中主要通过 let 关键字来声明变量的。

  • JS是一门弱类型语言,变量是可以存放不同类型的值的。
<script>
    //变量
    let a = 20;
    a = "Hello";
    alert(a);
</script>

需要使用const关键字。一旦声明,常量的值就不能改变 (不可以重新赋值)。

<body>

    <script>
        //常量
        const PI = 3.14;
        PI = 3.15;
        alert(PI);
    </script>
</body>

3.函数

函数表达方式有两种:
第一种:
先看代码:

<body>
  <script>
    function add(a, b){
    return a + b;
    }

    let result = add(10,20);
    alert(result);

  </script>
</body>

就好像我们平时学习的编程语言一样,用名称来声明一个函数,并调用

第二种:
那我们也可以不为函数指定名字,那这一类的函数,我们称之为匿名函数。

  <script>
    // function add(a, b){
    // return a + b;
    // }

    // let result = add(10,20);
    // alert(result);
    
    var add = function (a,b){
    return a + b;
    }

    var add = (a,b) => {
    return a + b;
    }

    let result = add(10,20);
    alert(result);

  </script>

3.自定义对象
在学习这部分的时候,可以把它看作Java中的对象来学,先来看代码:

<script>
    //自定义对象
    let user = {
        name: "Tom",
        age: 10,
        gender: "男",
        sing: function(){
             console.log("悠悠的唱着最炫的民族风~");
         }
    }

    console.log(user.name);
    user.eat();
<script>

4.DOM:

DOM的核心思想:将网页的内容当做对象来处理,标签的所有属性在该对象上都可以找到,并且修改这个对象的属性,就会自动映射到标签身上。

DOM操作步骤:

  • 获取DOM元素对象
  • 操作DOM对象的属性或方法 (查阅文档)

常见操作:

 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-DOM</title>
</head>
<body>

  <h1 id="title1">11111</h1>
  <h1>22222</h1>
  <h1>33333</h1>

  
  <script>
    //1. 修改第一个h1标签中的文本内容
    //1.1 获取DOM对象
    // let h1 = document.querySelector('#title1');
    //let h1 = document.querySelector('h1'); // 获取第一个h1标签

    let hs = document.querySelectorAll('h1');

    //1.2 调用DOM对象中属性或方法
    hs[0].innerHTML = '修改后的文本内容';
    
  </script>
    
  </script>
</body>
</html>

在这里插入图片描述

JS事件监听语法

形式: 事件源.addEventListener(‘事件类型’, 要执行的函数);

常见事件源:
黑马程序员文档图片

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS事件</title>
</head>
<body>
  
  <input type="button" id="btn1" value="点我一下试试1">
  <input type="button" id="btn2" value="点我一下试试2">

  <script>

    document.querySelector("#btn1").addEventListener("click",function(){
      alert("点击了按钮1");
    });

    document.querySelector("#btn2").addEventListener("click",function(){
      alert("点击了按钮2");
    });
    
  </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

最后来具体写一个案例来看看Js在项目中的具体实现吧

还是来看看前端的页面来了解功能:

在这里插入图片描述

通过JS为上述的表格中数据行添加事件监听, 实现鼠标进入后, 背景色#f2e2e2; 鼠标离开后, 背景色需要设置为#fff; (JS新版本的语法)

来看看代码吧:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Tlias智能学习辅助系统</title>
    <style>
        /* 导航栏样式 */
        .navbar {
            background-color: #b5b3b3; /* 灰色背景 */
            
            display: flex; /* flex弹性布局 */
            justify-content: space-between; /* 左右对齐 */

            padding: 10px; /* 内边距 */
            align-items: center; /* 垂直居中 */
        }
        .navbar h1 {
            margin: 0; /* 移除默认的上下外边距 */
            font-weight: bold; /* 加粗 */
            color: white;
            /* 设置字体为楷体 */
            font-family: "楷体";
        }
        .navbar a {
            color: white; /* 链接颜色为白色 */
            text-decoration: none; /* 移除下划线 */
        }

        /* 搜索表单样式 */
        .search-form {
            display: flex;
            flex-wrap: nowrap;
            align-items: center;
            gap: 10px; /* 控件之间的间距 */
            margin: 20px 0;
        }
        .search-form input[type="text"], .search-form select {
            padding: 5px; /* 输入框内边距 */
            width: 260px; /* 宽度 */
        }
        .search-form button {
            padding: 5px 15px; /* 按钮内边距 */
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd; /* 边框 */
            padding: 8px; /* 单元格内边距 */
            text-align: center; /* 左对齐 */
        }
        th {
            background-color: #f2f2f2;
            font-weight: bold;
        }
        .avatar {
            width: 30px;
            height: 30px;
        }

        /* 页脚样式 */
        .footer {
            background-color: #b5b3b3; /* 灰色背景 */
            color: white; /* 白色文字 */
            text-align: center; /* 居中文本 */
            padding: 10px 0; /* 上下内边距 */
            margin-top: 30px;
        }

        #container {
            width: 80%; /* 宽度为80% */
            margin: 0 auto; /* 水平居中 */
        }
    </style>
</head>
<body>
    <div id="container">
        <!-- 顶部导航栏 -->
        <div class="navbar">
            <h1>Tlias智能学习辅助系统</h1>
            <a href="#">退出登录</a>
        </div>

        <!-- 搜索表单区域 -->
        <form class="search-form" action="/search" method="post">
            <label for="name">姓名:</label>
            <input type="text" id="name" name="name" placeholder="请输入姓名">

            <label for="gender">性别:</label>
            <select id="gender" name="gender">
                <option value=""></option>
                <option value="1"></option>
                <option value="2"></option>
            </select>

            <label for="position">职位:</label>
            <select id="position" name="position">
                <option value=""></option>
                <option value="1">班主任</option>
                <option value="2">讲师</option>
                <option value="3">学工主管</option>
                <option value="4">教研主管</option>
                <option value="5">咨询师</option>
            </select>

            <button type="submit">查询</button>
            <button type="reset">清空</button>
        </form>

        <!-- 表格展示区 -->
        <table>
            <!-- 表头 -->
            <thead>
                <tr>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>头像</th>
                    <th>职位</th>
                    <th>入职日期</th>
                    <th>最后操作时间</th>
                    <th>操作</th>
                </tr>
            </thead>

            <!-- 表格主体内容 -->
            <tbody>
                <tr>
                    <td>令狐冲</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>讲师</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任盈盈</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>咨询师</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>向问天</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任我行</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>教研主管</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>田伯光</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>班主任</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>不戒</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>班主任</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>左冷禅</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>定逸</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>东方兄弟</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>讲师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>金庸</td>
                    <td></td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>咨询师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 页脚版权区域 -->
        <footer class="footer">
            <p>江苏传智播客教育科技股份有限公司</p>
            <p>版权所有 Copyright 2006-2024 All Rights Reserved</p>
        </footer>
    </div>

    <script>
        //通过JS为上述的表格中数据行添加事件监听, 实现鼠标进入后, 背景色#f2e2e2; 鼠标离开后, 背景色需要设置为#fff; (JS新版本的语法)
        // 1. 获取所有的tr
        let trs = document.querySelectorAll('tbody tr');
        for(let i = 0; i < trs.length; i++){
            trs[i].addEventListener('mouseenter', function(){//鼠标进入事件
                this.style.backgroundColor = '#f2e2e2';
            });
            trs[i].addEventListener('mouseleave', function(){//鼠标出去事件
                this.style.backgroundColor = '#fff';
            });
        }
        
        
    </script>
</body>
</html>
  • 获取元素:document.querySelectorAll(‘tbody tr’) 使用了DOM方法 querySelectorAll 来选择文档中所有的 tr 元素,这些元素是 tbody 的子元素。这是一种基于CSS选择器来选取页面元素的方式,属于DOM操作的一部分。

  • 添加事件监听器:对于每个选中的 tr 元素,代码都为其添加了两个事件监听器,分别是鼠标进入 (mouseenter) 和鼠标离开 (mouseleave) 事件。这是通过调用DOM元素的方法 addEventListener 实现的。当这些事件被触发时,会执行相应的回调函数,从而改变当前行的背景颜色。

  • 修改样式:在事件处理函数内部,通过 this.style.backgroundColor 直接修改了元素的样式属性。这里的 this 指向的是当前处理事件的 tr 元素,而直接通过 style 属性来修改样式也是DOM操作的一种形式。

🙌先来从概念上大致了解一下Vue

Vue 是一款用于构建用户界面的渐进式的JavaScript框架。

在上面的这句话中呢,出现了三个词,分别是:构建用户界面、渐进式、框架。 我们来从这几个方面来具体看看他是干什么的。

  • Vue 是一个“框架”,它为你构建 Web 应用提供了坚实的基础和完整的解决方案。

  • 它的核心目标是“构建用户界面”,通过声明式渲染、组件化和响应式系统,让你能更轻松、高效地创建动态、交互丰富的 UI。

  • 渐进式中的渐进呢,字面意思就是 “循序渐进”。Vue生态中的语法呢是非常多的,比如声明式渲染、组件系统、客户端路由(VueRouter)、状态管理(Vuex、Pinia)、构建工具(Webpack、Vite)等等。意味着你可以自由选择从哪里开始、用多深,可以逐步采用,灵活集成,适应从小到大各种规模和复杂度的项目。

在这里插入图片描述

来从一个入门程序来看看它怎么使用

还是先来看看实现(因为是入门程序所也比较简单,主要看一下Vue的结构):

在这里插入图片描述

🤔来看看代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue-快速入门</title>
</head>
<body>

  <div id="app">
    <h1>{{ message }}</h1>
  </div>
  
  <script type="module">
    import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

    createApp({
      data() {
        return {
          message: 'Hello World!'
        }
      }
    }).mount('#app')
  </script>

</body>
</html>

1). 准备工作:

  • 准备一个html文件,并在其中引入Vue模块 (参考官方文档,复制过来即可)【注意:模块化的js,引入时,需要设置 type=“module”】
  • 创建Vue程序的应用实例,控制视图的元素
  • 准备元素(div),交给Vue控制

2). 数据驱动视图:

  • 准备数据。 在创建Vue应用实例的时候,传入了一个js对象,在这个js对象中,我们要定义一个data方法,这个data方法的返回值就是Vue中的数据。
  • 通过插值表达式渲染页面。 插值表达式的写法:{{…}}

Vue核心语法实战

概述
指令:指的是HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义,可以实现不同的功能 。例如:v-if,v-for…

形式:

<p v-xxx="....">.....</p>

常见指令:
在这里插入图片描述

1.响应式数据 — ref() 和 reactive()

"响应式"的意思是:当数据变化时,页面自动更新。你不需要手动操作 DOM(比如 document.getElementById(‘xxx’).innerHTML = …),Vue 帮你做了。

这是 Vue 最核心的能力,也是所有现代前端框架(React、Vue、Angular)的核心思想。

⭐ ref() 的基本用法

import { ref } from 'vue'

// ref() 把一个普通值"包装"成响应式对象
const temperature = ref(26.5)
const deviceName = ref('温度传感器-001')
const isOnline = ref(true)

// ★ 在 JS 中访问/修改 ref 的值,必须用 .value
temperature.value = 28.0
console.log(temperature.value)  // 28.0

// ★ 在 template 中使用时,Vue 自动解包,不需要 .value
// <p>{{ temperature }}</p>  ← 直接写变量名就行

⭐ reactive() 的基本用法

import { reactive } from 'vue'

// reactive() 直接让对象变成响应式,不需要 .value
const sensor = reactive({
  id: 1,
  name: '温度传感器-001',
  value: 26.5,
  unit: '°C',
  online: true
})

// 直接修改属性即可
sensor.value = 28.0
sensor.online = false

🔥 ref vs reactive 怎么选?

在这里插入图片描述

2. v-for

作用:列表渲染,遍历容器的元素或者对象的属性
语法:

<tr v-for="(item,index) in items" :key="item.id">{{item}}</tr>

参数:

  • items 为遍历的数组
  • item 为遍历出来的元素
  • index 为索引/下标,从0开始 ;可以省略,省略index语法: v-for = “item in items”
    key:
  • 作用:给元素添加的唯一标识,便于vue进行列表项的正确排序复用,提升渲染性能
  • 推荐使用id作为key(唯一),不推荐使用index作为key(会变化,不对应)
    注意:遍历的数组,必须在data中定义; 要想让哪个标签循环展示多次,就在哪个标签上使用 v-for 指令。

3. 条件渲染 — v-if vs v-show

⭐ v-if 与 v-show 基本用法

<!-- v-if:条件为 false 时,元素直接从 DOM 中移除 -->
<div v-if="temperature > 35">
  🔴 严重告警:温度过高!
</div>
<div v-else-if="temperature > 30">
  🟡 一般告警:温度偏高
</div>
<div v-else>
  🟢 正常运行中
</div>

<!-- v-show:条件为 false 时,元素还在 DOM 中,只是 display: none -->
<div v-show="isOnline">
  设备数据面板(仅在线时显示)
</div>

4. 模板语法 — 绑定一切

⭐ 文本插值 {{ }}

<!-- 基础用法:显示变量的值 -->
<p>{{ temperature }}</p>

<!-- 可以写 JS 表达式(注意:是表达式,不是语句) -->
<p>{{ temperature > 30 ? '⚠️ 过热' : '✅ 正常' }}</p>
<p>{{ deviceName.toUpperCase() }}</p>
<p>{{ `温度: ${temperature}°C` }}</p>

<!-- ⚠️ 这些不行(语句不是表达式):-->
<!-- {{ if (temperature > 30) { return '过热' } }}  ← 错误! -->
<!-- {{ let x = 1 }}  ← 错误! -->

5. ⭐ 属性绑定 v-bind (简写 😃

<!-- 动态绑定 HTML 属性 -->
<img :src="sensorIcon" :alt="deviceName" />

<!-- 动态绑定 class(最常用!) -->
<!-- 对象语法:class 名作为 key,布尔值作为 value -->
<div :class="{ 'online': isOnline, 'offline': !isOnline }">
  设备状态
</div>

<!-- 动态绑定 style -->
<div :style="{ color: temperature > 30 ? '#ff4444' : '#00ff88' }">
  {{ temperature }}°C
</div>

6.⭐ 事件绑定 v-on (简写 @)

<!-- 基础用法 -->
<button @click="handleClick">点击</button>

<!-- 内联写法(简单逻辑可以直接写) -->
<button @click="temperature += 0.5">升温</button>

<!-- 传参 -->
<button @click="setTemperature(25)">重置为 25°C</button>

<!-- 事件修饰符(实际开发中非常有用) -->
<form @submit.prevent="handleSubmit">  <!-- .prevent 阻止默认行为 -->
<button @click.stop="handleClick">     <!-- .stop 阻止事件冒泡 -->
<input @keyup.enter="handleSearch">    <!-- .enter 回车键触发 -->

⭐ 双向绑定 v-model

<!-- v-model 用于表单元素,实现数据的双向绑定 -->
<!-- 输入框的值改变 → 变量自动更新 → 页面其他地方也自动更新 -->
<input v-model="deviceName" placeholder="输入设备名称" />
<p>你输入的设备名:{{ deviceName }}</p>

<!-- 本质上,v-model 是一个语法糖,等价于: -->
<input :value="deviceName" @input="deviceName = $event.target.value" />

来看看案例:

先看看前端页面(其实跟前面的实现差不多,但我们主要看代码,Vue简化了不少)
在这里插入图片描述

来看看代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tlias智能学习辅助系统</title>
    <style>
      body {
        margin: 0;
      }

      /* 顶栏样式 */
      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        background-color: #c2c0c0;
        padding: 20px 20px;
        box-shadow: 0 2px 5px rgba(0,0,0,0.1);
      }
      
      /* 加大加粗标题 */
      .header h1 {
        margin: 0;
        font-size: 24px;
        font-weight: bold;
      }

      /* 文本链接样式 */
      .header a {
        text-decoration: none;
        color: #333;
        font-size: 16px;
      }

      /* 搜索表单区域 */
      .search-form {
        display: flex;
        align-items: center;
        padding: 20px;
        background-color: #f9f9f9;
      }

      /* 表单控件样式 */
      .search-form input[type="text"], .search-form select {
        margin-right: 10px;
        padding: 10px 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
        width: 26%;
      }

      /* 按钮样式 */
      .search-form button {
        padding: 10px 15px;
        margin-left: 10px;
        background-color: #007bff;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }

      /* 清空按钮样式 */
      .search-form button.clear {
        background-color: #6c757d;
      }

      .table {
         min-width: 100%; 
         border-collapse: collapse;
      }

      /* 设置表格单元格边框 */
      .table td, .table th { 
        border: 1px solid #ddd; 
        padding: 8px; 
        text-align: center;
      }
      
      .avatar { 
        width: 30px; 
        height: 30px; 
        object-fit: cover; 
        border-radius: 50%; 
      }

      /* 页脚版权区域 */
    .footer {
        background-color: #c2c0c0;
        color: white;
        text-align: center;
        padding: 10px 0;
        margin-top: 30px;
    }

    .footer .company-name {
        font-size: 1.1em;
        font-weight: bold;
    }

    .footer .copyright {
        font-size: 0.9em;
    }

    #container {
      width: 80%;
      margin: 0 auto;
    }
    </style>
</head>
<body>
    
  <div id="container">
    <!-- 顶栏 -->
    <div class="header">
      <h1>Tlias智能学习辅助系统</h1>
      <a href="#">退出登录</a>
    </div>
    
    <!-- 搜索表单区域 -->
    <form class="search-form">
      <input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" />
      <select name="gender" v-model="searchEmp.gender">
          <option value="">性别</option>
          <option value="1"></option>
          <option value="2"></option>
      </select>
      <select name="job" v-model="searchEmp.job">
          <option value="">职位</option>
          <option value="1">班主任</option>
          <option value="2">讲师</option>
          <option value="3">学工主管</option>
          <option value="4">教研主管</option>
          <option value="5">咨询师</option>
      </select>
      <button type="button" @click="search">查询</button>
      <button type="button" @click="clear">清空</button>
    </form>

    <table class="table table-striped table-bordered">
      <thead>
          <tr>
              <th>姓名</th>
              <th>性别</th>
              <th>头像</th>
              <th>职位</th>
              <th>入职日期</th>
              <th>最后操作时间</th>
              <th>操作</th>
          </tr>
      </thead>
      <tbody>
        <tr v-for="(emp, index) in empList" :key="index">
          <td>{{ emp.name }}</td>
          <td>{{ emp.gender === 1 ? '男' : '女' }}</td>
          <td><img :src="emp.image" alt="emp.name" class="avatar"></td>
          <td>
            <span v-if="emp.job === '1'">班主任</span>
            <span v-else-if="emp.job === '2'">讲师</span>
            <span v-else-if="emp.job === '3'">学工主管</span>
            <span v-else-if="emp.job === '4'">教研主管</span>
            <span v-else-if="emp.job === '5'">咨询师</span>
          </td>
          <td>{{ emp.entrydate }}</td>
          <td>{{ emp.updatetime }}</td>
          <td class="btn-group">
            <button class="edit">编辑</button>
            <button class="delete">删除</button>
          </td>
        </tr>
      </tbody>
    </table>

    <!-- 页脚版权区域 -->
    <footer class="footer">
      <p class="company-name">江苏传智播客教育科技股份有限公司</p>
      <p class="copyright">版权所有 Copyright 2006-2024 All Rights Reserved</p>
    </footer>

    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
      createApp({
        data() {
          return {
            searchEmp: {
              name: '',
              gender: '',
              job: ''
            },
            empList: [
              { "id": 1,
                "name": "谢逊",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/4.jpg",
                "gender": 1,
                "job": "1",
                "entrydate": "2023-06-09",
                "updatetime": "2024-07-30T14:59:38"
              },
              {
                "id": 2,
                "name": "韦一笑",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg",
                "gender": 1,
                "job": "1",
                "entrydate": "2020-05-09",
                "updatetime": "2023-07-01T00:00:00"
              },
              {
                "id": 3,
                "name": "黛绮丝",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/2.jpg",
                "gender": 2,
                "job": "2",
                "entrydate": "2021-06-01",
                "updatetime": "2023-07-01T00:00:00"
              }
            ]
          }
        },
        methods: {
          search() {
            console.log(this.searchEmp)
          },
          clear() {
            this.searchEmp = {
              name: '',
              gender: '',
              job: ''
            }
          }
        }
      }).mount('#container')
    </script>

  </div>

</body>
</html>

来看看用到的Vue指令:
✅ 1. v-model:双向数据绑定

<input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" />
<select name="gender" v-model="searchEmp.gender">
  ...
</select>
<select name="job" v-model="searchEmp.job">
  ...
</select>
  • 作用:v-model 是 Vue 中最常用的指令之一,用于在表单元素(如 input、select、textarea)和 Vue 实例的数据之间建立双向数据绑定。
  • 解释:
    • 当用户在输入框中输入内容或选择下拉项时,searchEmp.name、searchEmp.gender、searchEmp.job 的值会自动更新。
    • 反之,如果在 JS 中修改了这些值,输入框或下拉框的显示也会同步更新。
  • 特点:它是语法糖,底层结合了 :value 和 @input 事件。

✅ 2. v-for:列表渲染

<tr v-for="(emp, index) in empList" :key="index">
  • 作用:用于循环渲染列表或数组中的每一项。
  • 解释:
    • 遍历 empList 数组中的每一个员工对象 emp。
    • 同时获取当前项的索引 index。
    • 每次循环生成一个 表格行。

✅ 3. v-if / v-else-if:条件渲染

<td>
  <span v-if="emp.job === '1'">班主任</span>
  <span v-else-if="emp.job === '2'">讲师</span>
  <span v-else-if="emp.job === '3'">学工主管</span>
  <!-- ... -->
</td>
  • 作用:根据表达式的真假值,动态地插入或移除 DOM 元素。
  • 解释:
    • 如果 emp.job === ‘1’ 为真,则只渲染“班主任”这个 。
    • 否则检查下一个条件,直到匹配或都不匹配。
  • 注意:v-else 和 v-else-if 必须紧跟在 v-if 后面。

✅ 4. {{ }}:插值表达式(Mustache Syntax)

<td>{{ emp.name }}</td>
<td>{{ emp.gender === 1 ? '男' : '女' }}</td>
  • 作用:将 Vue 实例中的数据动态插入到 HTML 文本中。
  • 解释:
    • {{ emp.name }} 直接显示员工姓名。
    • {{ emp.gender === 1 ? ‘男’ : ‘女’ }} 是一个三元表达式,根据 gender 值显示“男”或“女”。
  • 限制:只能包含单个 JavaScript 表达式,不能写语句(如 if、for)。

✅ 5. @click:事件绑定(v-on 的缩写)

<button type="button" @click="search">查询</button>
<button type="button" @click="clear">清空</button>
  • 作用:监听 DOM 事件,触发 Vue 实例中的方法。
  • 解释:
    • @click=“search” 是 v-on:click=“search” 的简写。
      点击“查询”按钮时,调用 methods 中定义的 search() 方法。
    • 点击“清空”按钮时,调用 clear() 方法。
  • 注意:这里使用 type=“button” 是为了避免表单提交刷新页面。

✅ 6. :(冒号):动态属性绑定(v-bind 的缩写)

<img :src="emp.image" alt="emp.name" class="avatar">
  • 作用:将 HTML 属性的值绑定为 Vue 中的动态数据。
  • 解释:
    • :src=“emp.image” 是 v-bind:src=“emp.image” 的简写。
    • 它会把 emp.image 的值作为图片的 src。

🌏先来看看什么是Ajax?

Ajax: 全称Asynchronous JavaScript And XML,异步的JavaScript和XML。其作用有如下2点:

  • 与服务器进行数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。
  • 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等。

如果想更多了解,可以看看官网 链接: https://www.axios-http.cn

来通过一个入门程序来看看Ajax怎么用

1. 先来来看看前端实现:

🙌点击按钮返回数据到控制台:
https://mock.apifox.cn/m1/3083103-0-default/emps/list:这个链接是黑马程序员提供的,能提供数据用于联系

在这里插入图片描述
来看看代码吧:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Axios入门程序</title>
</head>
<body>

  <button id="getData">GET</button>
  <button id="postData">POST</button>
  
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script>
    //GET请求
    document.querySelector('#getData').onclick = function() {
      axios({
        url:'https://mock.apifox.cn/m1/3083103-0-default/emps/list',
        method:'get'
      }).then(function(res) {
        console.log(res.data);
      }).catch(function(err) {
        console.log(err);
      })
    }
    
    //POST请求
    document.querySelector('#postData').onclick = function() {
      axios({
        url:'https://mock.apifox.cn/m1/3083103-0-default/emps/update',
        method:'post'
      }).then(function(res) {
        console.log(res.data);
      }).catch(function(err) {
        console.log(err);
      })
    }
  </script>
</body>
</html>

🙌来分析一下这段代码吧

  1. 引入 Axios 库
<!-- 引入 Axios 库 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  1. 👉 先加载 Axios,才能使用 axios() 发送请求。
// 1. 点击 GET 按钮,获取数据
document.querySelector('#getData').onclick = function() {
  axios({
    url: 'https://mock.apifox.cn/m1/3083103-0-default/emps/list', // 请求地址
    method: 'get'                                               // 请求方法
  })
  .then(function(res) {
    console.log(res.data); // 成功:打印返回的数据
  })
  .catch(function(err) {
    console.log(err);      // 失败:打印错误信息
  });
}

Axios还针对不同的请求,提供了别名方式的api,具体格式如下:
axios.请求方式(url [, data [, config]])
具体如下:
在这里插入图片描述

最后🎉我们基于axios动态加载员工列表数据

还是来看看前端界面,来了解一下案例:

进入页面是这样的(没有显示,以后会学钩子函数就会显示所有数据量了),在选项框中输入要查询的类别,点击查询后端就返回数据了:
在这里插入图片描述
在这里插入图片描述

来看看代码吧:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tlias智能学习辅助系统</title>
    <style>
      body {
        margin: 0;
      }

      /* 顶栏样式 */
      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        background-color: #c2c0c0;
        padding: 20px 20px;
        box-shadow: 0 2px 5px rgba(0,0,0,0.1);
      }
      
      /* 加大加粗标题 */
      .header h1 {
        margin: 0;
        font-size: 24px;
        font-weight: bold;
      }

      /* 文本链接样式 */
      .header a {
        text-decoration: none;
        color: #333;
        font-size: 16px;
      }

      /* 搜索表单区域 */
      .search-form {
        display: flex;
        align-items: center;
        padding: 20px;
        background-color: #f9f9f9;
      }

      /* 表单控件样式 */
      .search-form input[type="text"], .search-form select {
        margin-right: 10px;
        padding: 10px 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
        width: 26%;
      }

      /* 按钮样式 */
      .search-form button {
        padding: 10px 15px;
        margin-left: 10px;
        background-color: #007bff;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }

      /* 清空按钮样式 */
      .search-form button.clear {
        background-color: #6c757d;
      }

      .table {
         min-width: 100%; 
         border-collapse: collapse;
      }

      /* 设置表格单元格边框 */
      .table td, .table th { 
        border: 1px solid #ddd; 
        padding: 8px; 
        text-align: center;
      }
      
      .avatar { 
        width: 30px; 
        height: 30px; 
        object-fit: cover; 
        border-radius: 50%; 
      }

      /* 页脚版权区域 */
    .footer {
        background-color: #c2c0c0;
        color: white;
        text-align: center;
        padding: 10px 0;
        margin-top: 30px;
    }

    .footer .company-name {
        font-size: 1.1em;
        font-weight: bold;
    }

    .footer .copyright {
        font-size: 0.9em;
    }

    #container {
      width: 80%;
      margin: 0 auto;
    }
    </style>
</head>
<body>
    
  <div id="container">
    <!-- 顶栏 -->
    <div class="header">
      <h1>Tlias智能学习辅助系统</h1>
      <a href="#">退出登录</a>
    </div>
    
    <!-- 搜索表单区域 -->
    <form class="search-form">
      <input type="text" name="name" placeholder="姓名" v-model="searchForm.name" />
      <select name="gender" v-model="searchForm.gender">
          <option value="">性别</option>
          <option value="1"></option>
          <option value="2"></option>
      </select>
      <select name="job" v-model="searchForm.job">
          <option value="">职位</option>
          <option value="1">班主任</option>
          <option value="2">讲师</option>
          <option value="3">学工主管</option>
          <option value="4">教研主管</option>
          <option value="5">咨询师</option>
      </select>
      <button type="button" @click="search">查询</button>
      <button type="button" @click="clear">清空</button>
    </form>

    <table class="table table-striped table-bordered">
      <thead>
          <tr>
              <th>姓名</th>
              <th>性别</th>
              <th>头像</th>
              <th>职位</th>
              <th>入职日期</th>
              <th>最后操作时间</th>
              <th>操作</th>
          </tr>
      </thead>
      <tbody>
        <tr v-for="(emp, index) in empList" :key="index">
          <td>{{ emp.name }}</td>
          <td>{{ emp.gender === 1 ? '男' : '女' }}</td>
          <td><img :src="emp.image" alt="{{ emp.name }}" class="avatar"></td>
          
           <!-- 基于v-if/v-else-if/v-else指令来展示职位这一列 -->
          <td>
            <span v-if="emp.job == '1'">班主任</span>
            <span v-else-if="emp.job == '2'">讲师</span>
            <span v-else-if="emp.job == '3'">学工主管</span>
            <span v-else-if="emp.job == '4'">教研主管</span>
            <span v-else-if="emp.job == '5'">咨询师</span>
            <span v-else>其他</span>
          </td>

          <!-- 基于v-show指令来展示职位这一列 -->
          <!-- <td>
            <span v-show="emp.job === '1'">班主任</span>
            <span v-show="emp.job === '2'">讲师</span>
            <span v-show="emp.job === '3'">学工主管</span>
            <span v-show="emp.job === '4'">教研主管</span>
            <span v-show="emp.job === '5'">咨询师</span>
         </td> -->

          <td>{{ emp.entrydate }}</td>
          <td>{{ emp.updatetime }}</td>
          <td class="btn-group">
            <button class="edit">编辑</button>
            <button class="delete">删除</button>
          </td>
        </tr>
      </tbody>
    </table>

    <!-- 页脚版权区域 -->
    <footer class="footer">
      <p class="company-name">江苏传智播客教育科技股份有限公司</p>
      <p class="copyright">版权所有 Copyright 2006-2024 All Rights Reserved</p>
    </footer>

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
      createApp({
        data() {
          return {
            searchForm: {
              name: '',
              gender: '',
              job: ''
            },
            empList: []
          }
        },
        methods: {
          search() {
            //基于axios发送异步请求,请求https://web-server.itheima.net/emps/list,根据条件查询员工列表
            axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`).then(res => {
              this.empList = res.data.data
            })
          },
          clear() {
            this.searchForm= {
              name: '',
              gender: '',
              job: ''
            }
          }
        }
      }).mount('#container')
    </script>

  </div>

</body>
</html>

🌏Vue 3 脚本逻辑(核心):

<script type="module">
  import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
  
  createApp({
    data() {
      return {
        searchForm: { name: '', gender: '', job: '' },
        empList: []
      }
    },
    methods: {
      search() {
        axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`)
          .then(res => {
            this.empList = res.data.data
          })
      },
      clear() {
        this.searchForm = { name: '', gender: '', job: '' }
      }
    }
  }).mount('#container')
</script>

✅ data():定义响应式数据

  • searchForm:保存搜索条件(姓名、性别、职位)
  • empList:保存从服务器获取的员工列表数据(初始为空)

✅ methods:定义方法

  • search() :发送 Ajax 请求 获取员工列表

    • 使用 Axios 发送 GET 请求到后端 API。
    • 把搜索条件拼接到 URL 参数中。
    • 请求成功后,将返回的数据(res.data.data)赋值给 empList,Vue 会自动更新表格。
  • clear() :清空搜索条件
    当用户点击“清空”按钮时,clear() 方法会执行:👉 它把 searchForm 对象重新设置为初始状态(所有字段都为空字符串)。

什么是 ECharts?

ECharts 是百度开源的 JavaScript 数据可视化库,现在由 Apache 基金会维护。它可以帮你把数据变成各种图表:折线图、柱状图、饼图、地图、仪表盘、雷达图、散点图……几乎你能想到的图表它都支持。

安装 ECharts

在项目目录下执行:

cd E:/1_train/iot-screen
npm install echarts

安装完成后,package.json 的 dependencies 中会多出一行:

{
  "dependencies": {
    "vue": "^3.5.13",
    "echarts": "^5.x.x"    // ← 新增
  }
}

引入方式 — 全量引入 vs 按需引入:

// 方式一:全量引入(简单,但打包体积大 ~800KB)
// ★ 教学和原型阶段用这个,简单省事
import * as echarts from 'echarts'

// 方式二:按需引入(只引入用到的组件,体积小很多)
// ★ 正式项目上线前改成这个
import * as echarts from 'echarts/core'
import { LineChart, BarChart, PieChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent, GridComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

echarts.use([
  LineChart, BarChart, PieChart,
  TitleComponent, TooltipComponent, LegendComponent, GridComponent,
  CanvasRenderer
])

ECharts 的核心概念

使用 ECharts 只需要理解三样东西:

1. 容器(Container) —— 一个有宽高的 DOM 元素(div)
2. 实例(Instance)   —— 通过 echarts.init(容器) 创建
3. 配置(Option)     —— 一个 JS 对象,描述图表长什么样
准备一个 <div>(必须有宽高!)
       ↓
echarts.init(div) → 得到图表实例
       ↓
实例.setOption(配置对象) → 图表渲染出来
       ↓
数据变化时:再次调用 setOption(新配置) → 图表自动更新
       ↓
组件销毁时:实例.dispose() → 释放资源

在 Vue 3 中使用 ECharts 的标准模式

<template>
  <!--
    ★ 图表容器:
    1. 必须用 ref 绑定,方便 JS 中获取 DOM 元素
    2. 必须有明确的宽高(ECharts 需要知道画布大小)
  -->
  <div ref="chartRef" style="width: 100%; height: 100%"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'

// ==================== Step 1:获取 DOM 引用 ====================
// ref="chartRef" 绑定的 DOM 元素
const chartRef = ref(null)

// 图表实例(不用 ref 包裹,因为不需要响应式)
let chartInstance = null

// ==================== Step 2:定义配置项 ====================
const option = {
  // ... 图表配置(后面详细讲)
}

// ==================== Step 3:初始化图表 ====================
onMounted(() => {
  // 确保 DOM 已存在
  if (chartRef.value) {
    // 创建 ECharts 实例
    chartInstance = echarts.init(chartRef.value)
    // 设置配置项(图表就渲染出来了)
    chartInstance.setOption(option)
  }
})

// ==================== Step 4:清理资源 ====================
onUnmounted(() => {
  // ★ 必须 dispose!否则内存泄漏
  if (chartInstance) {
    chartInstance.dispose()
    chartInstance = null
  }
})
</script>

骨架搭好了,现在我们要给图表注入灵魂。option 对象就是 ECharts 的‘基因图谱’,它决定了图表长什么样。

那option怎么写呢?

最简单的方式, 就是直接到echarts的官网链接: https://echarts.apache.org/找, 找到你想要的图表, 然后直接复制完后改成自己想要的

网站里面图表非常丰富, 但是要改成我们自己想要的, 还需要了解Options不是:

Options所有的配置都遵循一个层级树状结构

option (根节点)
 ├── title (标题组件)
 ├── legend (图例组件)
 ├── grid (直角坐标系内绘图网格)
 │    ├── xAxis (x轴)
 │    └── yAxis (y轴)
 ├── series (系列列表,核心!)
 │    ├── type: 'line' (图表类型)
 │    ├── data: [...] (数据)
 │    └── itemStyle (图形样式)
 │         └── color: 'red'
 └── tooltip (提示框)

💡 核心规律:

  1. 组件独立:title、legend、tooltip 等都是平级的顶级属性。
  2. Series 是数组:series 是一个数组 [],因为一个图表可以同时画折线 + 柱状(混合图表)。
  3. 样式嵌套:具体的颜色、字体、边框通常藏在 itemStyle、label、lineStyle 等子对象里。

来看看什么是 ElementPlus

Element:是饿了么公司前端开发团队提供的一套基于 Vue3 的网站组件库,用于快速构建网页。

Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等。

官方网站: https://element-plus.org/zh-CN/#/zh-CN

你可能会有疑问,我们前面已经学过一些组件了,那为什么还要学ElementPlus呢?原因就是她更好看,有好多彩色按钮🥰,文本框也是圆圆的。

来看一个入门程序

package.json在终端打开

在这里插入图片描述

根据官方文档,安装ElementPlus组件库

npm install element-plus@2.4.4 --save

在main.js 中引入ElementPlus组件库 (参照官方文档),最终 main.js 中代码如下:

import { createApp } from 'vue'
import App from './App.vue'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)

app.mount('#app')

来从一个案例来学习ElementPlus组件

还是先来看看前端实现:

在这里插入图片描述
来看看代码吧

<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'


//表单
const emp = ref({
  name: '',
  gender: '',
  job: '',
})

//钩子函数
onMounted(() => {
  search();
})

//查询
const search = async () => {
  const url = `https://web-server.itheima.net/emps/list?name=${emp.value.name}&gender=${emp.value.gender}&job=${emp.value.job}`
  const result = await axios.get(url)
  empList.value = result.data.data
}

//清空
const clear = () => {
  emp.name = '';
  emp.gender = '';
  emp.job = '';
  search();
}

const empList = ref([])
</script>

<template>
  <!-- 搜索表单 -->
  <div id="container">
    <el-form :inline="true" :model="emp" class="demo-form-inline">
      <el-form-item label="姓名">
        <el-input v-model="emp.name" placeholder="请输入姓名" clearable />
      </el-form-item>
      <el-form-item label="性别">
        <el-select v-model="emp.gender" placeholder="请选择" clearable>
          <el-option label="" value="1" />
          <el-option label="" value="2" />
        </el-select>
      </el-form-item>
      <el-form-item label="职位">
        <el-select v-model="emp.job" placeholder="请选择" clearable>
          <el-option label="班主任" value="1" />
          <el-option label="讲师" value="2" />
          <el-option label="咨询师" value="3" />
        </el-select>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="search">查询</el-button>
        <el-button type="primary" @click="clear">清空</el-button>
      </el-form-item>
    </el-form>

    <!-- 表格 -->
    <el-table :data="empList" border style="width: 100%">
      <el-table-column prop="id" label="ID" width="80" align="center" />
      <el-table-column prop="name" label="姓名" width="100" align="center" />
      <el-table-column prop="image" label="头像" width="100" align="center" >
        <template #default="scope">
          <img :src="scope.row.image" width="50">
        </template>
      </el-table-column>
      <el-table-column prop="gender" label="性别" width="120" align="center" >
        <template #default="scope">
         {{ scope.row.gender == 1 ? '男' : '女' }}
        </template>
      </el-table-column>
      <el-table-column prop="job" label="职位" width="180" align="center" >
        <template #default="scope">
          <span v-if="scope.row.job == 1">班主任</span>
          <span v-else-if="scope.row.job == 2">讲师</span>
          <span v-else-if="scope.row.job == 3">咨询师</span>
          <span v-else>其他</span>
        </template>
      </el-table-column>
      <el-table-column prop="entryDate" label="入职日期" width="180" align="center" />
      <el-table-column prop="updatetime" label="更新时间" width="180" align="center" />
    </el-table>
  </div>


</template>

<style scoped>
#container {
   width: 70%;
  margin: auto;
  margin-top: 100px;


}

</style>

里面有许多技术,axios,Css,这里只介绍ElementPlus常见组件:

<template>

  <!-- 搜索表单 -->
  <div id="container">
    <el-form :inline="true" :model="emp" class="demo-form-inline">
      <el-form-item label="姓名">
        <el-input v-model="emp.name" placeholder="请输入姓名" clearable />
      </el-form-item>
      <el-form-item label="性别">
        <el-select v-model="emp.gender" placeholder="请选择" clearable>
          <el-option label="" value="1" />
          <el-option label="" value="2" />
        </el-select>
      </el-form-item>
      <el-form-item label="职位">
        <el-select v-model="emp.job" placeholder="请选择" clearable>
          <el-option label="班主任" value="1" />
          <el-option label="讲师" value="2" />
          <el-option label="咨询师" value="3" />
        </el-select>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="search">查询</el-button>
        <el-button type="primary" @click="clear">清空</el-button>
      </el-form-item>
    </el-form>

    <!-- 表格 -->
    <el-table :data="empList" border style="width: 100%">
      <el-table-column prop="id" label="ID" width="80" align="center" />
      <el-table-column prop="name" label="姓名" width="100" align="center" />
      <el-table-column prop="image" label="头像" width="100" align="center" >
        <template #default="scope">
          <img :src="scope.row.image" width="50">
        </template>
      </el-table-column>
      <el-table-column prop="gender" label="性别" width="120" align="center" >
        <template #default="scope">
         {{ scope.row.gender == 1 ? '男' : '女' }}
        </template>
      </el-table-column>
      <el-table-column prop="job" label="职位" width="180" align="center" >
        <template #default="scope">
          <span v-if="scope.row.job == 1">班主任</span>
          <span v-else-if="scope.row.job == 2">讲师</span>
          <span v-else-if="scope.row.job == 3">咨询师</span>
          <span v-else>其他</span>
        </template>
      </el-table-column>
      <el-table-column prop="entryDate" label="入职日期" width="180" align="center" />
      <el-table-column prop="updatetime" label="更新时间" width="180" align="center" />
    </el-table>
  </div>

</template>

1.用于构建表单结构。

<el-form :inline="true" :model="emp" class="demo-form-inline">
  <el-form-item label="姓名">
    <!-- 输入框 -->
  </el-form-item>
</el-form>

:inline=“true”:让表单项水平排列(行内布局)。
:model=“emp”:绑定表单数据模型,即 emp 对象。
el-form-item:每一个表单项的容器,label 属性设置标签名。

2.输入框组件,用于输入文本。

<el-input v-model="emp.name" placeholder="请输入姓名" clearable />

v-model=“emp.name”:双向绑定输入值。
placeholder:提示文字。
clearable:允许清空选择。

3.下拉选择器,用于性别和职位的选择。

<el-select v-model="emp.gender" placeholder="请选择" clearable>
  <el-option label="" value="1" />
  <el-option label="" value="2" />
</el-select>

v-model:绑定选中的值(如 emp.gender)。
clearable:允许清空选择。
el-option:定义每一个选项。

  • label:显示的文字。
  • value:实际绑定的值(字符串类型)。

4.按钮组件,用于触发操作。

<el-button type="primary" @click="search">查询</el-button>
<el-button type="primary" @click="clear">清空</el-button>

type=“primary”:主按钮样式(蓝色)。
@click:绑定点击事件,如 search() 和 clear() 方法。

5.表格组件,用于展示数据列表。

<el-table :data="empList" border style="width: 100%">
  <!-- 列定义 -->
</el-table>

:data=“empList”:绑定表格数据源(数组)。
border:显示边框。
style=“width: 100%”:宽度占满父容器。

6.定义表格的一列。

<el-table-column prop="name" label="姓名" width="100" align="center" />

prop:对应数据对象中的字段名(如 name, gender)。
label:列标题。
width:列宽。
align=“center”:内容居中对齐。

特殊列:使用 <template #default=“scope”>
对于需要 自定义渲染内容 的列(如图片、条件显示),使用 #default 插槽:

  1. 头像列(图片显示)
<el-table-column prop="image" label="头像" width="100" align="center">
  <template #default="scope">
    <img :src="scope.row.image" width="50">
  </template>
</el-table-column>

scope.row:当前行的数据对象。
渲染一个 标签,显示员工头像。

  1. 性别列(条件显示)
<template #default="scope">
  {{ scope.row.gender == 1 ? '男' : '女' }}
</template>
  1. 职位列(多条件判断)
<template #default="scope">
  <span v-if="scope.row.job == 1">班主任</span>
  <span v-else-if="scope.row.job == 2">讲师</span>
  <span v-else-if="scope.row.job == 3">咨询师</span>
  <span v-else>其他</span>
</template>

使用 v-if / v-else-if 根据 job 值显示对应职位名称。

VueRouter

先来简单介绍一下:

传统多页面应用(比如普通的 HTML 页面):跳转页面需要向服务器发请求,服务器返回新的 HTML 页面,页面会刷新,体验差、速度慢。( 而且还牵扯到跨域问题, 还需要在后端加@CrossOrigin允许访问,因为Vue Router 是「前端内部的页面切换」,不发跨域请求,很好的解决了这个问题 )

🧩扩展:
为什么 Vue Router 不会有跨域问题?
Vue Router 是前端路由,核心是「假装跳转页面」,本质是:

  1. 它只是修改浏览器地址栏的 URL(比如从 /home 跳到 /chart)
  2. 切换显示的 Vue 组件,全程没有向外部服务器发任何 HTTP 请求
  3. 所有操作都在「当前页面的域名(localhost:5173)」内部完成,完全不涉及跨域

扩展新手必懂的概念

1. 路由(Route)
就是「路径 + 对应组件」的映射关系。比如:

  • 访问 /home → 显示 Home.vue 组件
  • 访问 /chart → 显示 Chart.vue 组件

2. 路由器(Router)
管理所有「路由规则」的核心对象,相当于「导航员的总控台」,你需要创建它并配置所有路由规则。

在这里插入图片描述

  • :请求链接组件,浏览器会解析成
  • :动态视图组件,用来渲染展示与路由路径对应的组件

基础使用步骤(Vue3 + Vue Router4)

** 1:安装 Vue Router**

# npm 安装
npm install vue-router@4

2. 在 main.js 中挂载路由

import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入路由配置

const app = createApp(App)
app.use(router) // 挂载路由
app.mount('#app')

3.在 App.vue 中使用路由

<template>
  <div id="app">
    <!-- 路由链接:跳转按钮 -->
    <div class="nav">
      <router-link to="/home">首页</router-link>
      <router-link to="/chart">图表页</router-link>
    </div>
    <!-- 路由出口:组件渲染的位置 -->
    <router-view></router-view>
  </div>
</template>

<style>
/* 激活的链接高亮 */
.router-link-active {
  color: #00e5ff;
  font-weight: bold;
}
</style>

4.创建路由配置文件(src/router/index.js)

import { createRouter, createWebHistory } from 'vue-router'
// 导入你要跳转的组件
import Home from '../views/Home.vue'
import Chart from '../components/chart.vue' // 你的图表组件

// 定义路由规则
const routes = [
  {
    path: '/', // 默认路径
    redirect: '/home' // 重定向到首页
  },
  {
    path: '/home', // 路径
    name: 'Home',
    component: Home // 对应组件
  },
  {
    path: '/chart', // 图表页路径
    name: 'Chart',
    component: Chart // 你的图表组件
  }
]

// 创建路由器实例
const router = createRouter({
  history: createWebHistory(), // 采用HTML5 History模式(无#的URL)
  routes // 传入路由规则
})

export default router

嵌套式路由( 子组件 )

// 路由规则
{
  path: '/chart',
  component: Chart,
  children: [ // 子路由
    { path: 'trend', component: TrendChart }, // 对应 /chart/trend
    { path: 'data', component: DataChart } // 对应 /chart/data
  ]
}

// Chart.vue 中添加子路由出口
<router-view></router-view>

最后讲讲前端的部署吧

首先就肯定是要先打包:

直接双击npm脚本中的 build 即可将项目打包,打包后的文件会出现在 dist 目录中。
在这里插入图片描述

部署

打包完成之后,就可以将打包后的项目,部署到 nginx 服务器上了,

1) 先挂载配置, 在服务器上一般在/usr/root下新建数据卷挂载目录html和 配置文件存放目录 conf

扩展🧩

另外说一下nginx配置文件conf:

这里先了解两个重要的概念:

  1. 在VS_code 都是在在 vite.config.js 中配置前端请求服务器的信息, 当你把前端项目 npm build 打包后,它会变成一堆静态的 HTML/CSS/JS 文件

  2. Nginx 的作用:当你把前端项目放到 Nginx 的 html 目录下时,访问的是 Nginx 服务器(你的阿里云)。所有的前端请求(比如 /api/xxx),都是发给 Nginx 的,然后由 Nginx 转发给后端。

前端访问路径:
在这里插入图片描述

所以要修改nginx的配置文件:

server {
    listen       80; # 对外暴露 80 端口
    server_name  ; # 你的阿里云公网 IP

    # 前端页面访问(匹配 / 路径)
    location / {
        root   /usr/share/nginx/html; # 这里填你 dist 文件夹上传到服务器的路径
        index  index.html index.htm;
        # 解决 Vue 路由刷新 404 问题(如果用的是 history 模式)
        try_files $uri $uri/ /index.html;
    }

    # 后端 API 转发(匹配 /api 路径)
    location /api/ {
        # 重点:这里填你的后端服务在 Docker 网络里的地址
        # 因为后端叫 teacher-server,网络叫 teacher,所以直接写:
        proxy_pass http://teacher-server:8080/; 
        
        # 以下配置保持不变
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
    }
}

2)将前面打包好的目录html和 配置文件存放目录 conf,上传至服务器端的 /usr/local/tlias-web目录下。

  • 重新运行容器,同时挂载配置和网页目录
docker run -d \
--name nginx-container \
  -v /root/nginx/html:/usr/share/nginx/html \
  -v /root/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
  -v /root/nginx/conf/conf.d:/etc/nginx/conf.d \
--network itheima \
-p 80:80 \
nginx:1.20.2

小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

…。。。。。。。。。。。…

…。。。。。。。。。。。…请添加图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐