大家好 今天主要给大家带来了一个JavaWeb的开发入门!然后的话本期教程是由黑马程序员的视频:https://www.bilibili.com/video/BV1yGydYEE3H 来记录成的一个笔记。
一、HTML-CSS
1、Web前端的开发知识
①了解

前端代码是如何转换成用户现在能够看见的页面?是的 是浏览器

那既然在这个互联网上,那肯定具有一定的标准:

②网站演示
然后的话黑马程序员这时候为我们展示了一个小网站:

你会看见这个网站有很多的超链接,有很多的图片,但是布局很差,这是因为我们没有使用 css,那当我们加入CSS文件夹后:


但是你会发现点击按钮没有任何的反应?于是添加了个 JS 文件:


从这个网站小示例的话更能给你展现 HTML CSS JS 的主要作用

2、入门程序
①什么叫做HTML

什么叫做 HTML呢?那 HTML的基础格式是怎么样的?

②什么叫做css
什么叫做CSS呢?需要做什么工作内容?

其实很简单,我们只要拆开 <h1> 的标签栏(当然其他都可以)加入 style 的风格内容,不过相信大家肯定会知道这是什么意思,是的 这是让我们的字体变成红色!
接下来 黑马程序员给我们推荐了一个网站:https://developer.mozilla.org/zh-CN/

同时这里的话可以查看一些 HTML JS 等的文档,在这里你可以看见许多的代码示例

当然还有一些元素参考,在这边的话黑马程序员是推荐我们直接阅读英文文档 这样子比较原滋原味!

③开始入门

我们先了解一下大体的代码结构:首先的话 html 就是总体文件代码的包括,也就是说 <html> 这两个东西一定要在代码头尾,那么 <head> 呢?head就是给浏览器看的标识头,你在里面可以设置标题啊…导入css啊…等等。那么 <body> 就是我们网站的主体内容了!我们开始编写示例网站吧:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML快速入门</title>
</head>
<body>
<h1>HTML快速入门</h1>
<img src="./11.png">
</body>
</html>这样的话就成功完成了我们的入门练习…另外提一嘴 HTML代码并不是非常的严格规范,他不在意你的大小写,也不在意你的缺漏:

虽然给了你这么大的便利,但是你还是要好好遵守基本的代码规范!
小结:

3、常见的标签和样式
这边跳过了视频教程的软件安装,因为我的使用软件和AI不一样,黑马更趋向于 VSCODE + 通灵解码(或者豆包),我这边使用的是 WebStorm+Copilot 的组合。因此喜欢用什么都可以,VSCODE的安装教程以及插件安装:https://heuqqdmbyk.feishu.cn/wiki/YkgqwT32wivExHkpWtIcPcejnTd(黑马给的)
①标题-排版
Ⅰ创建标题(排版)

那我们开始剖析标题:

那我们先创建标题:
<h1>【新思想引领新征程】推进长江十年禁渔 谱写长江大保护新篇章</h1>你会好奇 h1到底是什么意思?别急!我给你解释:

然后的话我们要添加超链接(点击超链接可以直接跳转到):

<a href="https://www.cctv.com">央视网</a>
好 那我们开始解释一下超链接的分成部分:
<!--a 是超链接的标签:-->
<!--href 是超链接的属性:-->
<!--https://www.cctv.com 是超链接的属性值:-->
<!--target是打开方式:-->
<!--_blank是新窗口打开:-->
<!--_self是当前窗口打开:-->
<!--_parent是父窗口打开:-->
<!--_top是顶层窗口打开:-->那如果说我们想在新链接打开新闻网怎么打开?:
<a href="https://www.cctv.com" target="_blank">央视网</a>那时间呢?这样就可以:

来 看看我们这次学了什么东西:

Ⅱ增加颜色(样式)
你回发现我们的内容其实有点单调,你会发现:诶?咱时间不应该是灰色的吗?那这时候我们就要开始设置css了,首先给大家介绍下 导入CSS有三种方式:

那先展示下行内样式:
<span style="color: gray">2024年1月1日 10:10</span>接着是内部样式:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML快速入门</title>
<!-- 方式二:内部样式-->
<style>
span{
color: gray;
}
</style>
</head>
记得 style 标签是要在 head 标签里面的,后面的内容只要是 span 标签。里面的字就是用 sytle标签的样式!
比如说:
<span>2024年1月1日 10:10</span>这个标签就是灰色的。
好啦现在展示最后一种方式:外部样式,顾名思义就是直接引入外部文件。首先的话我们创建一个文件夹,文件夹里面创建一个css文件(喜欢咋样创建都可以 但是必须要有css文件)

那css里面的内容是什么呢?怎么塞入灰色的元素?别急 这样就行了:

<link rel="stylesheet" href="css/style.css">其中 href 就是你css文件的路径了!这样就完成!
但是你会发现一个小问题,就是你自己的灰色感觉还比央视新闻页面的样式还更深?


但是还是先给大家看看另外两种方式怎么表达吧!
<style>
span{
/*关键词表达法*/
/*color: gray;*/
/*RGB表达法:*/
/*color: rgb(255, 255, 255);*/
/*RGBA表达法:*/
/*color: rgba(128, 128, 128, 0.8); 其实这是在原来的基础上加了一个透明度*/
/*十六进制表达法:*/
/*color: #808080;*/
}
</style>RGB分开就是 RED GREEN BLUE 红绿蓝 根据数值来进行配对颜色,而RGBA 多了个A,就只是一个透明度的区别(透明度越低越看不见)。最后我们推荐的十六进制其实也差不多 前两位是红 中间绿 后面蓝色。
他们的阈值(比如说你想直接展示纯红色)RGB的值就是(255,0,0),十六进制就是(#FF0000)
那你说我要如何才能知道 央视新闻那个字体到底是什么颜色呢?我们需要拾色器(大部分的截图软件都有 包括QQ截图都有)这边推荐一个软件:snipaste

上小结:

ⅢCSS选择器
. 选择器

这是做什么的?如果你接触到刚刚前面的内容你会发现一个问题。就是我在 style 标签设置颜色后,每一个 span 标签内的颜色都是一样的。那如果有两个 span 标签,一个用了 style 标签的颜色,另一个不用 style标签。这要如何实现?
首先给大家介绍下类选择器:
/*类选择器*/
.cls{
color: red;
}引用方式:
<span class="cls">2024年1月1日 10:10</span>
这样的话你会发现两个文本颜色都不一样

那我们介绍下一个选择器:ID选择器,这是他的格式:
/*ID选择器*/
#time{
color: blue;
}使用方式:
<a href="https://www.cctv.com" id="time" target="_blank">央视网</a>同样的也是做一个颜色的区分,那如果说我同时用这三个标签,谁的优先级会更高呢?
ID选择器 > 类选择器 > 关键词表达法
这就是他们的优先级
.. 去超链接下划线

a{
/*去除超链接下方的下划线*/
text-decoration: none;
}这样就行了 直接丢进去 style 标签即可,因为我们标注的是 a 标签,所以不需要额外设定!诶,那你现在应该会很好奇 text-decoration 到底是做什么的?别急,我们打开MDN来看看!

点我查看:https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-decoration
然后补充下其他的选择器:

上小结:

②正文
Ⅰ排版
接下来的话我们就要开始还原正文部分了:

我们先来解释一下 video 元素:
<video src="video/test.mp4" controls autoplay width="600px"></video>
<!--video的标签属性:-->
<!-- src: 视频地址-->
<!-- controls: 显示视频的控制栏-->
<!-- autoplay: 自动播放-->
<!-- width: 视频的宽度(建议:宽度和高度只设置一个即可,另一个会等比例缩放)-->
<!-- height: 视频的高度-->
<!-- 单位:-->
<!-- px: 像素-->
<!-- %: 百分比-->其中的话 width 和 height 这个如果说你没把握好视频的像素大小 建议只设置一个否则会:

那百分比是什么意思?假如说我们设置了80%的百分比:

搞完这一部分 你会发现我们的视频和日期这一行在同一行:

那么就交给大家换行的代码:<br>

然后给大家多补充一个音频的插入:
<audio src="video/test.mp3" controls autoplay></audio>
<!--audio的标签属性:-->
<!-- src: 音频地址-->
<!-- controls: 显示音频的控制栏-->
<!-- autoplay: 自动播放-->没什么好说的,接下来我们开始继续看下面的正文!

你发现我们有两段落的内容,但是你发现一个问题 就是两段之间的内容有一个很大的空间,你用 br 标签换行都是紧贴着,那咋办?
这时候我们可以使用段落标签 p标签:
<p></p>代入到文本就是:


这样子的话就达成了我们的要求,接下来的话我们会看见一个gif图片:

如何操作:
<!--引入img/1.gif-->
<img src="img/1.gif" alt="长江大保护" width="600px">
<!--标签属性
src: 图片地址:
1. 相对路径:相对于当前html文件的位置
1.1 ./ : 当前文件夹(可以省略) 如:img/1.png
1.2 ../ : 上一级文件夹 如:../img/1.png
1.3 ../../ : 上上一级文件夹 如:../../img/1.png
2. 绝对路径:完整的网址路径
1.1绝对磁盘路径:C:/Users/Administrator/Desktop/1.png
1.2绝对网络路径:https://www.cctv.com/xxx/1.png
alt: 图片无法显示时,显示的替代文字
width: 图片宽度(建议设置一个 会自适应分配)
height: 图片高度
-->上小结:

Ⅱ样式
你会发现


“央视网消息”这几个字在原页面可是加粗的,这时候就要交给大家两个加粗的标签:
<b></b><strong></strong>
下一步的话我们就要开始设置字里行间的行高:

p {
line-height: 1.5; /*行高1.5倍*/
font-size: 20px; /*字体大小20px*/
}塞进 style 就行了 针对 P标签进行的操作。还需要什么参数可以直接看 MDN 即可!接下来的话我们要对这个段落进行缩进两格:
不要傻傻的打空格,打空格给自己看的不是编译器看的,因此我们要用 来代替你的空格:

一个 就是一个空格,但是这种方式不太优雅,我们要换一个更好的方法,比如说添加在刚刚的css上:
line-height: 1.5; /*行高1.5倍*/
font-size: 20px; /*字体大小20px*/
text-indent: 2em; /*首行缩进2个字符*/
}2em就是两个字符,同时也可以设置百分比(%)和像素(px)


③整体布局
Ⅰ调整布局
我们先来对比下央视新闻的页面和我们自己写的页面:



代码解析:
<div id="content-container" style=""></div>这两个 div 之间就是你body内的网页内容,CSS:
#content-container
{
width: 70%; /*内容宽度800px*/
margin-left: auto;
margin-right: auto; /*水平居中*/
}补上去代码后你会发现确实居中了:

但是又有一个新的问题 就是视频的宽度怎么和字不是一块宽的?

Ⅱ盒子模型
诶!你都还没给我解释上一节的margin是什么玩意诶?别急!这部分给你慢慢解释!



那我们随便设置了一个盒子模型的模块:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>盒子模型</title>
</head>
<body>
<div id="div1">
A A A A A A A A A A A A A A
</div>
<div id="div2">
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>
<span>
B B B B B B B b B B B B BB b BB B
</span>
<span>
B B B B B B B b B B B B BB b BB B
</span>
</body>
</html>那这么多模块在一起如何判断这个是谁的span 哪个是谁的 div?点击 F12 结果就有!


同时的话也可以设置这些 style 在上面(在这里就是更好区分一下div那些位置):
<style>
#div1 {
width: 400px;
height: 300px;
background: aqua;
}
</style>
也可以添加我们上面说的 padding:
padding: 50px;
#div1 {
width: 400px; /*宽度:400像素;默认说明内容区宽度*/
height: 200px; /*高度:200像素;默认说明内容区高度*/
background: aqua;
margin: 50px; /*外边距:50像素*/
padding: 50px; /*内边距:50像素*/
box-sizing: border-box;
border: 10px solid red; /*边框:10像素实线红色*/
}

具体的话可以看这个文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/margin
那如果说你希望这个盒子模型可以直接居中呢?

在 margin 的参数后面添加一个 auto 意思即为居中
小结:

②tlias案例

Ⅰ顶部导航栏
首先的话我们来看导航栏:

这个导航栏的主要组成部分为:一个网站标题 + 退出登陆的超链接
黑马程序员在这里直接使用 AI 来进行生成(原画):
你是一名前端开发工程师,现需要制作一个HTML页面,这个页面共分为4个部分,先实现第一个部分 – 顶部导航栏。 具体需求如下: 内容: 要展示一个醒目(加粗加粗展示)的标题,标题内容: Tlias智能学习辅助系统:还要展示一个“退出登录”的超链接。,布局: 标题和退出登录的超链接,展示在一行里面。 标题居左显示, 退出登录的超链接居右展示。3.给整个顶部导航栏, 设置一个灰色的背景色。
请帮我生成这个HTML页面。
这是我的AI给我生成的页面:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: #f0f0f0;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
</body>
</html>然后你会看见我们的页面上这样的:

那如果说我们想把这个标题的颜色改成白色而且有字体的话,然后这个背景色改得更深,该如何改呢?

其实的话不难发现AI做这些代码,还是能看出怎么写的。这边class标签很清楚了,按照图片上的红色标记进行修改即可。
颜色背景的话其实很好改,就改background-color就行了。

然后更改文字颜色和字体只需要添加这两行即可

这就是改完后的标题内容:
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}Ⅱflex布局
当你看见导航栏主体代码的时候:
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}你会很好奇这些东西到底是什么作用?为什么文字标题和退出登陆的超链接会整齐的左一个 右边一个,左右对其是因为 justify-content: space-between; 是一个左右对齐的参数。但是的话这一部分我们主要讲的是 flex 布局

黑马程序员准备了一个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex布局</title>
<style>
#container {
blackground-color: red;
width: 500px;
height: 500px;
}
.item {
width: 100px;
height: 50px;
border: 1px solid gray;
blackground-color: blue;
}
</style>
</head>
<body>
<div id="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
body {
margin: 0;
}只需要添加这个参数就可以了
但是你会发现一个问题,就是当我调整浏览器窗口大小的时候,里面的框框都是不会发生改变的,这时候就可以开始请上我们的 flex 布局了!
#container {
blackground-color: red;
width: 500px;
height: 500px;
display: flex;
}因为我们的布局名称设定成 container 所以说直接添加 display: flex 即可!
当我们打开弹性布局的时候,弹性布局有一个参数叫做:flex-direction: row; 他的默认参数是 row 水平的意思(水平分布,设置主轴)那我们设置完这些后,如何设置排布方式呢?这时候我们就要讲解另一个参数了:justify-content: flex-start;
添加完,诶你会发现,怎么还是一样的?这是因为 flex-start 就是从头开始分布,相反过来 flex-end 就是从尾部开始分布,center就是从中间开始分布…这些参数很多很多

Ⅲ表单标签
接下来的话我们将进入表单标签的制作:


接下来就展示一个简单的表单:
<body>
<!-- form表单:
action:表单数据提交的url地址
method:提交方式
get:默认
name的话这边主要是起到变量ID的作用,到时候取值就是name的变量
-->
<form action="/save" method="get">
姓名:<input type="text" name="name">
年龄:<input type="text" name="age">
</form>
</body>
<input type="submit" value="提交">但是你会发现提交后是没有反应的(同时你也会发现链接成功跳转到 save了):

因此的话我们要开始设置内容,可以让客户端这边把数据给传送到服务端那边,首先的话要先改成 POST 模式:

当我们改完后上传数据后 你会看见:

所以说我们介绍下 get 和 post 之间的区别:
get:默认,表单数据会出现在url后面,形式:?name=zhangsan&age=20
特点:
1.如果表单中包含了隐私数据,get方式不安全
2.数据量有限制,url长度有限制,不适合大量数据提交
post:表单数据放在请求体中,安全性高,数据量大,一般用于数据新增和修改
特点:
1.数据量大,没有长度限制
2.安全性高,数据不会出现在url中
3.一般用于数据新增和修改
注意:表单项要想能够采集数据,必须得设置name属性,表示当前表单项名字
上小结:

Ⅳ表单项标签
那我们现在来给大家讲解表单项标签,这是什么?比如说密码也有专门的标签(就自己打*号什么的)那我们来看看有哪些表单项:

我们直接放一个实例代码给大家参考:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单项标签</title>
</head>
<body>
<form action="/save" method="POST">
姓名:<input type="text" name="name" placeholder="请输入姓名" required>
<br>
密码:<input type="password" name="password" placeholder="请输入密码" required>
<br>
性别:
<input type="radio" name="gender" value="1"> 男
<input type="radio" name="gender" value="2"> 女
<br>
爱好:
<input type="checkbox" name="hobby1" value="1"> 篮球
<input type="checkbox" name="hobby2" value="2"> 足球
<input type="checkbox" name="hobby3" value="3"> 乒乓球
<br>
头像: <input type="file" name="avatar">
<br>
日期: <input type="date" name="date">
<br>
生日: <input type="datetime-local" name="birthday">
<br>
时间: <input type="time" name="time">
<br>
城市:
<select name="city">
<option value="">--请选择--</option>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
</select>
<br>
备注:
<textarea name="remark" cols="30" rows="5" placeholder="请输入备注"></textarea>
<br>
<input type="submit" value="提交">
<input type="reset" value="重置">
<input type="button" value="按钮">
</form>
</body>
</html>页面是这样的:

然后给大家特别说明下几个位置:

当这个选择标签中name是一样的时候,只能是单选,name不一样就是多选

我们对数据进行提交(查看浏览器载荷):

你肯定会很好奇说 诶?为什么 gender是1 而不是男啊?因为他读取的是value的值啊
同时的话我给大家介绍一下 label 标签,他到底有什么好处?
性别:
<input type="radio" name="gender" value="1"> 男
<label><input type="radio" name="gender" value="2"> 女</label>如代码所示,我们只单独给女的括上了 Label 标签,但是你发现在点击的时候你会发现一个问题。

上小结:

Ⅴtlias案例-搜索表单区域
刚刚我们的表单说到顶部导航栏的位置,从这边开始我们继续讲解我们的 tlias 案例。

这边黑马程序员依旧使用了AI来进行生成代码,这是AI的对话:
接下来,再帮我生成第二个部分-搜索表单区域,具体说明如下:
- 组成:包括三个表单项和两个操作按钮。
1.1表单项具体为:姓名(文本输入框)、性别(下拉选择,选项包括 男/女,
默认为空)、职位(下拉选择,选项包括班主任、讲师、学工主管、教研主管、咨询师,默认为空)。
1.2两个技钮:“查询”与“清空”按钮,用于提交表单 或 重置表单项。 - 布局:所有表单项及按钮需水平排列于一行,确保美观大气。
生成的最终代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
</style>
</head>
<body>
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
<label>
性别:
<select name="gender">
<option value="">--请选择--</option>
<option value="男">男</option>
<option value="女">女</option>
</select>
</label>
<label>
职位:
<select name="position">
<option value="">--请选择--</option>
<option value="班主任">班主任</option>
<option value="讲师">讲师</option>
<option value="学工主管">学工主管</option>
<option value="教研主管">教研主管</option>
<option value="咨询师">咨询师</option>
</select>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
</body>
</html>这是AI生成的地方,但是有一些东西AI的习惯不太好,比如说 value 虽然说写成中文便于我们识别内容,但是对于后端处理来说比较麻烦,我建议改成:

在给大家展示一个比较特殊的地方:

也就是说这个 css 部分的 search-form 这个大类下的 input 和 select 都会使用这个 css:

Ⅵtlias-表格数据展示区域
接下来的话我们要开始编辑这个部分:

黑马程序员还是用AI对话来进行生成代码,这是对话内容:
再继续帮我生成第三个部分-表格展示区:
1.表格结构:展示列包括姓名、性别(显示男/女)、头像(小图片展示)、职位(显示班主任/讲师/学工主管/教研主管/
咨询师)、入职日期、最后操作时间、操作(里包含两个按钮 编辑 与删除)。测试数据:基于《笑傲江湖》小说人物在表格中生成3条测试数据,每条数据应包含上述所有列的信息,以体现实际应用场景。3. 样式:可适当调整表格样式,确保美观大气。
看看我代码生成的最终结果:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
</style>
</head>
<body>
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
<label>
性别:
<select name="gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select 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>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
<!--下面的区域就是表格的区域-->
<table class="data-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 src="https://i.imgur.com/1X5QH6F.png" alt="令狐冲" class="avatar"></td>
<td>讲师</td>
<td>2020-03-15</td>
<td>2024-06-01 10:23</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>任盈盈</td>
<td>女</td>
<td><img src="https://i.imgur.com/8Km9tLL.png" alt="任盈盈" class="avatar"></td>
<td>咨询师</td>
<td>2021-07-22</td>
<td>2024-06-02 09:10</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>岳不群</td>
<td>男</td>
<td><img src="https://i.imgur.com/5cLDezB.png" alt="岳不群" class="avatar"></td>
<td>教研主管</td>
<td>2018-11-05</td>
<td>2024-05-30 16:45</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>网页展示:

我们剖析下代码的内容:



| 表格 | 中文意思 | 作用 |
| tr(table row) | 表格行 | 可以存储多个人的数据(以本实例代码为例子,如:小明、张三) |
| th(table head) | 表格头 | 存储个人的各种数据(如:性别、爱好等) |
| td(table data) | 表格数据 | 个人的数据,如:18岁、足球等 |

Ⅶtlias-底部版权区域

这次的话黑马程序员还是继续使用AI生成代码,这是对话:
再继续帮我生成第四个部分-页脚版权区域
- 内容:第一行显示公司全称“XXXXXX公司”:第二行展示版权信息,“版权所有 Copyright 2025 All Rights Reserved”。
2.设计:该区域应具有灰色背景,字体颜色为白色,居中对齐,以营造专业且统一的视觉效果。
最终生成的代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
/*这是页脚区域*/
.footer {
background: #444;
color: #fff;
text-align: center;
padding: 20px 0 18px 0;
font-size: 16px;
margin-top: 32px;
letter-spacing: 1px;
line-height: 1.7;
}
</style>
</head>
<body>
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
<label>
性别:
<select name="gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select 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>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
<!--下面的区域就是表格的区域-->
<table class="data-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 src="https://i.imgur.com/1X5QH6F.png" alt="令狐冲" class="avatar"></td>
<td>讲师</td>
<td>2020-03-15</td>
<td>2024-06-01 10:23</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>任盈盈</td>
<td>女</td>
<td><img src="https://i.imgur.com/8Km9tLL.png" alt="任盈盈" class="avatar"></td>
<td>咨询师</td>
<td>2021-07-22</td>
<td>2024-06-02 09:10</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>岳不群</td>
<td>男</td>
<td><img src="https://i.imgur.com/5cLDezB.png" alt="岳不群" class="avatar"></td>
<td>教研主管</td>
<td>2018-11-05</td>
<td>2024-05-30 16:45</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
</body>
<!-- 页脚版权区域 -->
<footer class="footer">
<div>XXXXXX公司</div>
<div>版权所有 Copyright 2025 All Rights Reserved</div>
</footer>
</html>然后给大家介绍下每个区域:

这是一个页脚区域是可以包含在 body 区块内的。再看一看它的CSS相关区域:

然后的话这一部分主要是解释 margin-top 这个东西,这玩意其实是body和页脚之间的距离:

最后的话你会发现我们的表格占据的空间很大,想要把整个页面缩小:


然后在 style 这边设置css:
#container {
width: 80%;
margin: 0 auto;
}width 就是占据整个页面的 80%,margin的第一个参数是上下不动,左右居中(auto)
完结!HTML的学习部分就到这结束了,这里给大家送上完整的 tlias 的代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
/*这是页脚区域*/
.footer {
background: #444;
color: #fff;
text-align: center;
padding: 20px 0 18px 0;
font-size: 16px;
margin-top: 32px;
letter-spacing: 1px;
line-height: 1.7;
}
#container {
width: 80%;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="container">
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
<label>
性别:
<select name="gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select 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>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
<!--下面的区域就是表格的区域-->
<table class="data-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 src="https://i.imgur.com/1X5QH6F.png" alt="令狐冲" class="avatar"></td>
<td>讲师</td>
<td>2020-03-15</td>
<td>2024-06-01 10:23</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>任盈盈</td>
<td>女</td>
<td><img src="https://i.imgur.com/8Km9tLL.png" alt="任盈盈" class="avatar"></td>
<td>咨询师</td>
<td>2021-07-22</td>
<td>2024-06-02 09:10</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
<tr>
<td>岳不群</td>
<td>男</td>
<td><img src="https://i.imgur.com/5cLDezB.png" alt="岳不群" class="avatar"></td>
<td>教研主管</td>
<td>2018-11-05</td>
<td>2024-05-30 16:45</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
<footer class="footer">
<div>XXXXXX公司</div>
<div>版权所有 Copyright 2025 All Rights Reserved</div>
</footer>
</div>
</body>
</html>4、HTML课程总结


二、JavaScript
1、课程介绍

效果展示的话大概就是这样做:


那我们要如何导入JS呢?

示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS引入方式</title>
</head>
<body>
<!-- javascript脚本引入方式:-->
<!-- 1.内联式:<script>js代码</script>-->
<!-- 2.内嵌式:<script src="js文件路径"></script>-->
<!-- 3.外联式:<script src="js文件路径"></script>-->
<script>
alert("内联式");
</script>
<script src="js/JS-引入方式-内嵌式.js"></script>
<script src="js/JS-引入方式-外联式.js"></script>
</body>
</html>如果说当你把JS丢到 head中 或者html标签外的 都会触发!

上小结:

2、核心语法
①变量&常量

与其他编程差别大的就是,常量的值赋值过后就不能再赋值了。那我们来看示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS-基础语法</title>
</head>
<body>
<script>
// 1.声明变量
let a = 10;
a = "Hello";
a = true
alert(a);
// 2.声明变量
const PI = 3.14;
// PI = 3.14159; // 报错,常量不能修改
console.log(PI); // 输出在控制台中
document.write(PI); // 输出在页面中
</script>
</body>
</html>其实说有个编程基础,基本都看得懂。

上小结:

②数据类型

示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS-数据类型</title>
</head>
<body>
<script>
// 1.基本数据类型
// 数字类型:number
let num1 = 10;
let num2 = 3.14;
console.log(typeof num1); // number
console.log(typeof num2); // number
alert(typeof true); // boolean
alert(typeof false); // boolean
alert(typeof "Hello"); // string
alert(typeof 'JS'); // string
alert(typeof `ES6`); // string
alert(typeof undefined); // undefined
alert(typeof null); // object
alert(typeof null);
let a;
console.log(a); // undefined
console.log(typeof a); // undefined
</script>
</body>
</html>
示例代码:
let name = 'Tom';
let age = 20;
console.log('我是'+name+',今年'+age+'岁'); // 我是Tom,今年20岁
console.log(`我是${name},今年${age}岁`); // 我是Tom小结:

③函数
函数介绍:

注意:由于JS是弱类型语言,形参、返回值都不需要指定类型。在调用函数时,实参个数与形参个数可以不一致,但是建议一致。
函数这个东西,如果说你接触过其他代码的话,你应该知道这玩意的主要用处就是避免代码的复用性。也就是说当你包含一块代码需要大量重复使用的话,你就可以用函数把这块代码打包起来,通过函数来进行调用即可。来看示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS-函数</title>
</head>
<body>
<script>
// 1. 函数定义及调用
function add(a,b){
return a + b;
}
let result = add(10,20); // 函数调用
console.log(result); // 30
</script>
</body>
</html>
示例代码:
// 2. 函数定义及调用 - 匿名函数
// 2.1 函数表达式
let sub = function(a,b){
return a - b;
}
let res = sub(20,10);
console.log(res); // 10
// 2.2 箭头函数
let mul = (a,b) => {
return a * b;
}
let r = mul(10,20);
console.log(r); // 200小结:

④自定义对象

示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS-自定义对象</title>
</head>
<body>
<script>
// 1. 自定义对象
let person = {
name: "张三",
age: 20,
gender: "Male",
sayHello: function(){
console.log("Hello, I'm " + this.name);
}
};
console.log(person.name); // 访问对象属性
// 2. 调用对象属性/方法
alert(person.age);
person.sayHello();
</script>
</body>
</html>函数形式可以进行简化:

诶 那你肯定又要说了,咱刚刚不是讲了箭头函数嘛?怎么不用了?注意:在箭头函数中,this并不指向当前对象 – 指向的是当前对象的父级 所以我们这不推荐使用!
上小结:

⑤JSON
那什么东西叫做JSON呢?

如果说你有在这方面研究过的话 你会发现很多网站的 API 都是这种格式。来看看示例代码:
let json = {
"name": "李四",
"age": 25,
"isStudent": false,
"scores": [90, 85, 88],
"address": {
"city": "北京",
"zip": "100000"
}
};
alert(JSON.stringify(json)); // JS对象—》字符串打开浏览器的时候就会看见:

这个就是标准的 JSON,那我们如何直接获取到JSON文本内的内容呢?
let jsonStr = '{"name":"李四","age":25,"isStudent":false,"scores":[90,85,88],"address":{"city":"北京","zip":"100000"}}';
alert(JSON.parse(jsonStr).name); // 字符串—》JS对象这样就可以直接提取到 name 的内容了。
上小结:

⑥DOM
什么叫做DOM呢?

那关于DOM的操作是如何的?

关于 DOM操作,查看属性或者方法,黑马程序员这不太推荐使用 MDN 来作为参考的文档,而是推荐了W3Schools:https://www.w3school.com.cn/
那我们来看示例代码,来看如何调用 h1 并且修改 h1 中的内容:
<body>
<h1 id="title1">11111</h1>
<h1>22222</h1>
<h1>33333</h1>
<script>
// DOM - 文档对象模型
// 1. 获取元素
let h1 = document.getElementById("title1");
h1.innerText = "Hello";
</script>
</body>还有一个办法:
let hs = document.getElementsByTagName("h1");
hs[0].innerHTML = '<em>你好</em>';这边的[0],就是第一个h1 ,顺序都是按0开始的
上小结:

3、事件监听
①介绍


接下来来看配置好的代码:
<input type="button" id="btn1" value="按钮1">
<input type="button" id="btn2" value="按钮2">
<script>
// 事件监听 - Event Listener
let btn1 = document.getElementById("btn1");
btn1.onclick = function () {
alert("按钮1被点击了");
};
</script>还有另一种写法,但是我们只需要理解即可!

// 事件绑定 - 早期的事件绑定方式 onclick
document.querySelector("#btn2").onclick = function () {
alert("按钮2被点击了");
}那新版本的写法和现在的写法有什么区别?:

也就是说 addEventListener 这个方法可以绑定多个事件,那如果是 onclick 的话,后面的事件会覆盖前面的事件
上小结:

②案例学习
这个案例的名字叫做:实现表格数据行鼠标移入移出隔行换色效果

提示:通过js实现鼠标移入移出隔行换色效果,鼠标移入时,背景色为#f2e2e2;鼠标移出,背景色统一显示白色
黑马程序员在这里使用了AI的辅助功能来进行制作:

<script>
//通过Js为上述的表格中数据行添加事件监听,实现鼠标进入后,背景色#f2e2e2;鼠标离开后,背景色需要设置为#FFF;
let rows = document.querySelectorAll(".data-table tbody tr");
rows.forEach(row => {
row.addEventListener("mouseenter", () => {
row.style.backgroundColor = "#f2e2e2";
});
row.addEventListener("mouseleave", () => {
row.style.backgroundColor = "#fff";
});
});
</script>其实的话这个代码 你看的话大概率是可以看懂的,比如说我们选取的数据 .data-table tbody tr 你肯定能知道是我们代码中的数据表格那些…监听事件中的 mouseenter你也能知道这肯定是鼠标进入的事件!
③常见事件
哪还有什么事件呢?

代码格式如下:

但是你会发现 我们输出的内容是不是都是类似的,比如说都是控制台输出?这时候你肯定想说用函数,那如何正确函数呢?这可不是一般的 script 标签导入了!

那如何把另一个 JS 文件直接导入进去呢?JS是什么?JavaScript,Java!这时候我们就可以直接使用Java的import 来进行导入!
import ( priftlog ) from "./util.js";这样就可以了!就可以直接使用 printlog 来使用函数参数了!补充函数的格式:(export就是导出,一定要加)
export function PrintLog(msg){
console.log(msg)
}使用就是:
PrintLog("XXXXX");
但是你会发现,怎么控制台报错了?别急,这是因为你没有声明这个js文件为模块化文件,所以会产生报错!因此我们需要告诉HTML,我们使用的JS是模块化的JS!
<script src="demo.js" type="module"></script>添加到 body 标签内即可!这样的话可以提高代码的复用性,同时也降低了我们的维护成本!
三、Vue
1、快速入门
关于VUE到底是什么呢?Vue是一款用于构建用户界面的渐进式的JavaScript框架。官网地址:https://cn.vuejs.org/ 我们来举例子带大家进入本课程:

为什么呢?gender:1 是什么东西?男的还是女的?因此我们需要VUE来进行转换,将数据从后端提取出来,通过VUE的转换来传送到前端给用户看:



那接下来的时间我们需要对VUE开始展开工作了!

Vue其实的话你可以直接理解为 JS 的 模块,和我们上面说的一样 都是 module 也是通过Java的语法import来进行导入。最后面的话 .mount(“#app”) 和我们的CSS选择器的语法一样,直接定位到上面的 DIV 的ID。到时候div 那块区域就可以直接使用 Vue来!

先展示一个代码的示例,这是一个准备数据的过程 在 script 标签内的 createApp({}) 他是对象,在接下来的一层的 data() 就是方法,return的话是一个返回值,返回了什么?返回了一个mssage
然后我们需要通过差值表达式来渲染页面,也就是图片上画红线的地方(最上面)。其中的话{{message}}就是一个差值表达式


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue-快速入门</title>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<h1>{{count}}</h1>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data(){
return{
message: 'Hello Vue!',
count: 100
}
},
}).mount('#app');
</script>
</body>
</html>注意:显示的内容一定要在 div标签 id app 内才可以显示 Vue内容。如果没显示 可能是网络问题
小结:

2、常用指令

那我们就进入案例开始搞!:
①v-for

这时候的话其实就可以通过遍历的方式,将这三个数据分别遍历上去,那我们就不由得提到了 v-for
那我们看看 v-for的定义吧:

注意:遍历的数组,必须在data中定义;要想让哪个标签循环展示多次,就在哪个标签上使用v-for指令。
示例代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
/*这是页脚区域*/
.footer {
background: #444;
color: #fff;
text-align: center;
padding: 20px 0 18px 0;
font-size: 16px;
margin-top: 32px;
letter-spacing: 1px;
line-height: 1.7;
}
#container {
width: 80%;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="container">
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
<label>
性别:
<select name="gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select 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>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
<!--下面的区域就是表格的区域-->
<table class="data-table">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>头像</th>
<th>职位</th>
<th>入职日期</th>
<th>最后操作时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="emp in emPlist" :key="emp.id">
<td>{{emp.name}}</td>
<td>{{emp.gender == 1?'男' : '女'}}</td>
<td><img src="{{emp.image}}" alt="{{emp.name}}" class="avatar"></td>
<td>{{emp.position}}</td>
<td>{{emp.hireDate}}</td>
<td>{{emp.lastModified}}</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
<footer class="footer">
<div>XXXXXX公司</div>
<div>版权所有 Copyright 2025 All Rights Reserved</div>
</footer>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data(){
return{
emPlist: [
{
"id": 1,
"name": "令狐冲",
// 帮我根据上面的内容继续写完下面的json数据
"image": "https://i.imgur.com/1X5QH6F.png",
"gender": 1,
"position": "讲师",
"hireDate": "2020-03-15",
"lastModified": "2024-06-01 10:23"
},
{
"id": 2,
"name": "任盈盈",
"image": "https://i.imgur.com/2X5QH6F.png",
"gender": 2,
"position": "咨询师",
"hireDate": "2021-07-22",
"lastModified": "2024-05-30 14:12"
},
{
"id": 3,
"name": "岳灵珊",
"image": "https://i.imgur.com/3X5QH6F.png",
"gender": 2,
"position": "班主任",
"hireDate": "2019-11-05",
"lastModified": "2024-06-02 09:45"
}
]
}}}).mount('#container')
</script>
</body>
</html>那我们对下面的代码进行剖析:


其中 emp in emPlist 这句话的意思是:我们定义了一个数据叫做 emp(提取到每组数据),数据是从我们 CreateApp 中的 emPlist提取,后面的 key 其实就是判断每组数据的标识,比如说 id,有id才知道这是第一组数据 第二组数据这样,然后接下来的 td 标签中的数据其实很容易看出什么意思,比如说 emp.name 就是从我们自己定义的emp中提取name的数据,以此类推。
上小结:

②v-bind
在上部分的时候我们有用到 v-for 但是你会发现一个问题:

为什么会出现这个问题,是因为插值表达式是不能出现在标签内部的,那我们如何在标签的属性来动态的赋一个值呢?所以这时候我们就要用 v-bind 这个命令了!

注意:动态的为标签的属性绑定值,不能使用插值,得使用 v-bind 指令。且绑定的数据,必须在data中定义
我们对代码进行修改:
<td><img v-bind:src="emp.image" :alt="emp.name" class="avatar"></td>基本的格式就是这样子 前面加上v-bind: 然后插值表达式删除即可,如果后面也需要用上 v-bind,可以不用输入 直接键入: 就可以省略了(如:alt)
上小结:

③v-if & v-show

现在查看我们的需求,我们会发现职位上显示的数字是 1 2 3 4 但是我们希望能够显示右边的班主任啊 讲师等等内容。所以这时候我们就要用到了条件语句:

注意:v-else-if必须出现在v-if之后,可以出现多个;v-else必须出现在v-if/v-else-if之后。
示例代码:
<td>
<span v-if="emp.position == 1">班主任</span>
<span v-if="emp.position == 2">讲师</span>
<span v-if="emp.position == 3">学工主管</span>
<span v-if="emp.position == 4">教研主管</span>
<span v-if="emp.position == 5">咨询师</span>
<span v-if="emp.position == 6">其他</span>
</td>其实的话很好理解 就是把原来的 td 表格中的数据直接插入 span 数据即可。

那 v-show 要如何敲写呢?:
<td>
<span v-show="emp.position == 1">班主任</span>
<span v-show="emp.position == 2">讲师</span>
<span v-show="emp.position == 3">学工主管</span>
<span v-show="emp.position == 4">教研主管</span>
<span v-show="emp.position == 5">咨询师</span>
</td>其实很简单 直接替换就可以了

上小结:

④v-model
我们先来看一个案例:

正如图上所见 v-model 是一个采集数据的命令(当用户进行搜索数据时使用),v-on是一个事件绑定的命令(当用户点击查询或者清空键执行的操作)
那我们先开始来看 v-model,首先的话我们需要先封装用户输入的查询条件:

然后到达我们填写查询姓名的地方,绑定搜索的内容:
<label>
姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>修改后:
<label>
姓名:
<input type="text" id="name" name="name" v-model="searchForm.name" placeholder="请输入姓名">
</label>剩下的也一起修改:



这边的话黑马程序员推荐了个浏览器插件,可以根据我们的 v-model 存在的数据进行修改验证,下载地址:https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?utm_source=ext_app_menu



搞定完后我们就要来开始操作点击 查询 和 清空 后执行的事件了
⑤v-on
为了执行这个操作,我们需要用到 v-on 这个命令:


<button type="submit" v-on:click="search">查询</button>
<button type="reset">清空</button>直接到我们的 Vue 配置的地方,添加一个和data 同级的method:




需要注意的是:methods函数中的this指向Vue实例,可以通过 this 获取到 data中定义的数据。
源码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
/*这是页脚区域*/
.footer {
background: #444;
color: #fff;
text-align: center;
padding: 20px 0 18px 0;
font-size: 16px;
margin-top: 32px;
letter-spacing: 1px;
line-height: 1.7;
}
#container {
width: 80%;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="container">
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" action="#" method="GET">
<label>
姓名:
<input type="text" id="name" name="name" v-model="searchForm.name" placeholder="请输入姓名">
</label>
<label>
性别:
<select id="gender" name="gender" v-model="searchForm.gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select id="position" name="position" 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>
</label>
<button type="submit" @click="search">查询</button>
<button type="reset" v-on:click="clear">清空</button>
</form>
{{searchForm}}
<!--下面的区域就是表格的区域-->
<table class="data-table">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>头像</th>
<th>职位</th>
<th>入职日期</th>
<th>最后操作时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="emp in emPlist" :key="emp.id">
<td>{{emp.name}}</td>
<td>{{emp.gender == 1?'男' : '女'}}</td>
<td><img v-bind:src="emp.image" :alt="emp.name" class="avatar"></td>
<!-- <td>-->
<!-- <span v-if="emp.position == 1">班主任</span>-->
<!-- <span v-if="emp.position == 2">讲师</span>-->
<!-- <span v-if="emp.position == 3">学工主管</span>-->
<!-- <span v-if="emp.position == 4">教研主管</span>-->
<!-- <span v-if="emp.position == 5">咨询师</span>-->
<!-- <span v-if="emp.position == 6">其他</span>-->
<!-- </td>-->
<td>
<span v-show="emp.position == 1">班主任</span>
<span v-show="emp.position == 2">讲师</span>
<span v-show="emp.position == 3">学工主管</span>
<span v-show="emp.position == 4">教研主管</span>
<span v-show="emp.position == 5">咨询师</span>
</td>
<td>{{emp.hireDate}}</td>
<td>{{emp.lastModified}}</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
<footer class="footer">
<div>XXXXXX公司</div>
<div>版权所有 Copyright 2025 All Rights Reserved</div>
</footer>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data(){
return{
searchForm:{
name: '',
gender: '',
job: ''
},
emPlist: [
{
"id": 1,
"name": "令狐冲",
// 帮我根据上面的内容继续写完下面的json数据
"image": "https://i.imgur.com/1X5QH6F.png",
"gender": 1,
"position": 1,
"hireDate": "2020-03-15",
"lastModified": "2024-06-01 10:23"
},
{
"id": 2,
"name": "任盈盈",
"image": "https://i.imgur.com/2X5QH6F.png",
"gender": 2,
"position": 2,
"hireDate": "2021-07-22",
"lastModified": "2024-05-30 14:12"
},
{
"id": 3,
"name": "岳灵珊",
"image": "https://i.imgur.com/3X5QH6F.png",
"gender": 2,
"position": 3,
"hireDate": "2019-11-05",
"lastModified": "2024-06-02 09:45"
}
]
}},
methods: {
search(){
console.log(this.searchForm);
},
clear(){
this.searchForm = {name:'', gender:'', job:''}
}
}}).mount('#container')
</script>
</body>
</html>上小结:

四、Ajax
1、入门
什么叫做 Ajax,这是干什么的?:

XML:(英语:Extensible Markup Language)可扩展标记语言,本质是一种数据格式,可以用来存储复杂的数据结构。
这时候会给大家扩展到一个东西,就是同步和异步的区别:

接下来给大家推荐一个项目助力于 ajax 的开发

使用方法也是和我们前面的 Vue 一样 也是通过 JS 来导入:

然后的话大家可以看下面的示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Axios-入门</title>
</head>
<body>
<input type="button" value="GET" id="btnGet">
<input type="button" value="POST" id="btnPost">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 1. GET请求
document.getElementById("btnGet").onclick = function () {
axios({
url: "https://jsonplaceholder.typicode.com/posts/1",
method: "GET"
}).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.log(error);
});
};
// 2. POST请求
document.getElementById("btnGet").onclick = function () {
axios({
url: "https://jsonplaceholder.typicode.com/posts/1",
method: "POST"
}).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.log(error);
});
};
</script>
</body>
</html>这个就是 axios 的基本格式,其中的 URL 只是一个 JSON数据的页面(给你实验用的),后面的两块内容我们上文也解释过了就是成功访问后的 response 和 error提示。


其实的话代码也有一种简化的方式:

然后给大家解释下黄色和红色的地方,代码并不是说从上按下来执行的,如果说因为你的网络卡顿(黄色地方),并不会影响到红色方框内的内容输出的,所以大概率是红色部分先输出出来,而不是等服务端相响应出来继续执行下去。这也是体现了异步
上小结:

2、案例

服务端URL地址:https://web-server.itheima.net/emps/list(里面还是一样的性质,放的都是JSON的数据,2025年10月11日该站存活)我们需要做的是在删除本地记录的前提下能让服务端来动态获取链接的数据来展示出来。


第一行 code:1 的内容就相当于网站访问成功了,第二行的 msg 就是提示输出。剩下的部分就是data的数据内容了。
我们先把之前完整的Vue案例示例代码的内容复制过来,删除原来 emPlist 中的所有数据:

记得补 axios 的JS链接:

清空之后我们添加一下黑马程序员的JSON网址:

但是你会不会觉得数据内容是不是很单调,对的我们需要对数据内容分别做一个拼接,比如说拼接 name gender 和 job
methods: {
search(){
// 1. 发送ajax请求
axios.get('https://web-server.itheima.net/emps/list?name=' + this.searchForm.name + '&gender=' + this.searchForm.gender + '&position=' + this.searchForm.job).then((res) => {
console.log(res.data)
this.empList = res.data
})
// 另一种链接拼接的方法:
// axios.get('https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender&position=${this.searchForm.job')
},这样拼接就可以了 另外的话我们设置了如果真的获取到数据了,要把数据内容丢给emPlist当中:

搞定完后我们可以在网站页面中看见我们的数据:

示例代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Tlias智能学习辅助系统</title>
<style>
.navbar {
background-color: darkgray;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar-title {
font-weight: bold;
font-size: 20px;
color: white;
font-family: Arial, sans-serif;
}
.navbar-logout {
text-decoration: none;
color: #333;
font-size: 16px;
}
.navbar-logout:hover {
text-decoration: underline;
}
.search-form {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
background: #fff;
margin-top: 16px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search-form label {
display: flex;
align-items: center;
gap: 4px;
font-size: 16px;
}
.search-form input,
.search-form select {
padding: 4px 8px;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 2px;
}
.search-form button {
padding: 5px 18px;
font-size: 15px;
cursor: pointer;
border: none;
border-radius: 2px;
background: #f0f0f0;
transition: background 0.2s;
}
.search-form button:hover {
background: #e0e0e0;
}
/*表格区域的css*/
.data-table {
width: 100%;
border-collapse: collapse;
margin: 24px 0;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
border-radius: 6px;
overflow: hidden;
font-size: 16px;
}
.data-table th, .data-table td {
padding: 12px 16px;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
.data-table th {
background: #f5f5f5;
font-weight: bold;
}
.data-table tr:last-child td {
border-bottom: none;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
border: 1px solid #eee;
}
.action-btn {
padding: 4px 14px;
margin: 0 2px;
border: none;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
background: #f0f0f0;
transition: background 0.2s;
}
.action-btn.edit {
color: #1976d2;
}
.action-btn.delete {
color: #d32f2f;
}
.action-btn:hover {
background: #e0e0e0;
}
/*这是页脚区域*/
.footer {
background: #444;
color: #fff;
text-align: center;
padding: 20px 0 18px 0;
font-size: 16px;
margin-top: 32px;
letter-spacing: 1px;
line-height: 1.7;
}
#container {
width: 80%;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="container">
<div class="navbar">
<span class="navbar-title">Tlias智能学习辅助系统</span>
<a href="#" class="navbar-logout">退出登录</a>
</div>
<form class="search-form" @submit.prevent="search" @reset.prevent="clear" action="#" method="GET">
<label>
姓名:
<input type="text" v-model="searchForm.name" placeholder="请输入姓名">
</label>
<label>
性别:
<select v-model="searchForm.gender">
<option value="">--请选择--</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</label>
<label>
职位:
<select v-model="searchForm.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>
</label>
<button type="submit">查询</button>
<button type="reset">清空</button>
</form>
<!--下面的区域就是表格的区域-->
<table class="data-table">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>头像</th>
<th>职位</th>
<th>入职日期</th>
<th>最后操作时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="emp in emPlist" :key="emp.id">
<td>{{emp.name}}</td>
<td>{{emp.gender == 1 ? '男' : '女'}}</td>
<td><img :src="emp.image" :alt="emp.name" class="avatar"></td>
<td>{{emp.position}}</td>
<td>{{emp.entrydate}}</td>
<td>{{emp.updatetime}}</td>
<td>
<button class="action-btn edit">编辑</button>
<button class="action-btn delete">删除</button>
</td>
</tr>
</tbody>
</table>
<footer class="footer">
<div>XXXXXX公司</div>
<div>版权所有 Copyright 2025 All Rights Reserved</div>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/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{
emPlist: [],
searchForm: {
name: '',
gender: '',
position: ''
}
}},
methods: {
search(){
// 1. 发送ajax请求
axios.get('https://web-server.itheima.net/emps/list?name=' + this.searchForm.name + '&gender=' + this.searchForm.gender + '&position=' + this.searchForm.position).then((res) => {
this.emPlist = res.data.data;
})
// 另一种链接拼接的方法:
// axios.get('https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender&position=${this.searchForm.job')
},
clear(){
// 2. 清空表单
this.searchForm = {name: '',gender: '', position: ''}
this.emPlist = []
}
}
}).mount('#container')
</script>
</body>
</html></title>
</head>
<body>
</body>
</html>
注意:await关键字只在async函数内有效,await关键字取代then函数,等待获取到请求成功的结果值。
就是这样:
let res = await axios.get('https://web-server.itheima.net/emps/list?name=' + this.searchForm.name + '&gender=' + this.searchForm.gender + '&position=' + this.searchForm.position).then((res) => {
this.emPlist = res.data.data;这样的话我们算是基本搞完了吧?
3、思考

这时候就提到了 Vue 的生命周期



让我们进入示例代码:

实际上只要添加下这些内容即可:
mounted(){
// 页面加载完成后,获取所有员工信息
this.search();
}所以如果想要页面加载完毕后执行某一件操作,那我们可以借助于Vue生命周期相关的钩子操作可以实现
上小结:

五、Maven
1、课程介绍

Maven这个东西也是比较重要的,只要设计到Java开发,就基本需要Maven


那关于Maven的作用我就和大家说吧:

①依赖管理
我们在开发项目的时候可能会用到一些第三方插件的依赖,按照之前的思路的话,我们要先从官网上下载第三方的Jar包下来,然后丢进项目的 Lib中:

才可以使用,但是今天我们有了Maven之后,这一切操作都不需要了



这样就可以创建出一个Maven的项目了



②项目构建
在我们项目构建的时候会产生一个Javac(但是你用IDE这种编译器比较多,基本上看不见javac这一部分),但是的话Maven可以帮你进行编译、测试、打包、发布这一步骤

那我们就开始从编译开始:




③统一项目结构


这是我们的课程目录:

2、概述-介绍&安装
①介绍


那我们找的这些包都在哪里找?都是要去我们的仓库中来进行寻找

还有一种叫做私服,这种方式一般都是公司内部自己搭建的远程仓库。


上小结:

②安装



这节课不多说,因为大部分人都有
3、IDEA集成
①配置Maven环境(全局)




这样的话我们全局配置基本就完成了
我们来一个Maven的案例:创建Maven项目:




到此为止 一个完整的 Maven 文件目录结构,那我们先创建一个 Hello World 的输出,构建之后你会发现目录下会多出来几个文件:

②Maven坐标
什么叫做Maven坐标:

当你点开项目的时候你会看见版本号有一个SNAPSHOT:

这是什么意思呢?:

上小结:

③导入Maven项目
导入Maven项目的方法有很多种:
Ⅰ方式一:

那我们从第一种方式开始讲起:



Ⅱ方式二


上小结:

4、依赖管理
➀依赖配置

回到源代码中,你会发现添加多个依赖很简单:







不过你实在不想要还有一个是排除依赖
➁排除依赖

实例代码:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.2.11</version>
<exclusions>
<exclusion>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-commons</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>最终刷新一下依赖就跑掉了,上小结:

➂生命周期

阶段非常的多,但是我们只需要关注五个阶段就行了:


注意:在同一套生命周期中,当运行后面的阶段时,前面的阶段都会运行。

回到IDEA,当我们执行Clean的时候:


当我们按编译(compile)的时候 target 又会回来了,当我们点击install的时候:

[INFO]
[INFO] --- jar:3.4.1:jar (default-jar) @ maven_project01 ---
[INFO] Building jar: /Users/zherking/Documents/JavaPractice/JavaWeb_Project/maven_project01/target/maven_project01-1.0-SNAPSHOT.jar
[INFO] 命令行咱直接跳过了,毕竟用IDEA了(其实大体命令就是 mvn clean这种),接下来我们来看Maven的大体结构:


上小结:

六、单元测试
1、概述&入门
➀概述
首先来的话给大家介绍下什么叫做测试:

那我们这边先插入三种测试的形式:

带入到我们的测试当中就是这样:

好了,这儿说完 我们就开始对单元测试来进行解释
Ⅰ单元测试


接着我们来看一个入门程序的需求 案例:使用JUnit,对userService中业务方法进行单元测试。
首先的话Junit是一个第三方的框架

注意:JUnit单元测试类名命名规范为:xxxxxTest【规范】。JUnit单元测试的方法,必须声明为 public void 【规定】
回到我们的示例代码当中,我们先加载依赖:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.14.0</version>
<scope>test</scope>
</dependency>
</dependencies>我们随便找一个代码来进行测试:
package com.mclzyun;
import org.junit.jupiter.api.Test;
public class UserServiceTest {
@Test
public void testGetAge() {
UserService userService = new UserService();
int age = userService.getAge();
assert age == 25 : "Expected age to be 25, but got " + age;
}
}


上小结:
1.JUnit单元测试是做什么的?
- 测试类中方法的正确性
2.JUnit单元测试的优点是什么?
- 测试代码与应用程序代码分开,使于维护
- 可以自动生成测试报告(通过:绿色,失败:红色)
- 一个测试方法执行失败,不会影响其它测试方法
3.JUnit单元测试的命名规范?
- 方法:public void xxxx(){…}(规定)
- 类:XxxxTest(规范)
2、断言&常见注解
我们先来思考一个问题:

比如说我们接下来的代码:

⓵断言
那我们接下来就要给大家介绍下什么是断言:

提示:上述方法形参中的最后一个参数 msg,表示错误提示信息,可以不指定(有对应的重载方法)。


上小结:

⓶常见注解
在JUnit中还提供了一些注解,还增强了其功能,常见的注解有以下几个:






但是如果说你觉得这个测试类的名称并不是很美观,你可以通过这样进行修改:

上小结:

⓷企业开发规范
Ⅰ入门

我有点懒 有点不想去公众号去拿课程资料,没有什么新的代码,只有演示:




那你说如果你不想测试HelloWord 只想要单独测试UserService呢?你需要这么做:




Ⅱ案例


登陆完后点击代码内容即可进行单元测试

其实我不是很想说什么 因为后面的内容基本都是对AI内容的东西进行分析
④Maven依赖范围(单元测试)


是因为在 Maven 中,他们提供Main主要是写主程序,而Test是进行单元测试的。但是你一定要在非Main中进行单元测试的也不是不行,这时候需要我们来借助Maven的依赖范围



如果说你在编译的时候不想要测试,也能直接跳过测试的阶段:

上小结:

⑤常见的问题和解决方案





操作完之后打开IDEA 继续刷新下Maven项目就可以了,如果说Maven还继续爆红,关掉IDEA重新打开项目即可
七、Web基础
1、课程安排




2、SpringBootWeb入门
①入门程序
SpringBoot官网:spring.io


我们正式进入课程教学:

步骤:

首先的话我们先来创建一个SpringBoot项目:




其中的话在Main中的 SpringBootWebQuickStartApplication是主要的启动类,紧接着resource下的static是主要存放静态类文件(比如说HTML CSS这些),然后templates是放模版类文件(暂时用不上)。application.properties是主要的核心文件(也暂时用不上)
最后的Test就是测试类文件,创建SpringBoot这一步骤就完成了接下来就是定义Controller类

示例代码:(带注释)
package com.mclzyun;
import org.springframework.web.bind.annotation.RestController;
@RestController // 表示当前类是一个控制器类,处理HTTP请求并返回响应数据
public class HelloController {
@RequestMapping("/hello") // 映射HTTP请求到该方法,路径为/hello 比如说访问地址 http://localhost:8080/hello
public String hello(String name) { // 定义一个处理请求的方法,接受一个name参数 比如说访问地址 http://localhost:8080/hello?name=McLzyun
return name + "Hello, Spring Boot!";
}
}

上小结:

②无法连接Spring网站解决
一些同学可能会遇到一个问题就是Spring官方脚手架链接不上:


阿里云的Spring 地址:
https://start.aliyun.com更换上就行了
③入门程序剖析


3、HTTP协议
①概述

就是两个人互相发电报 然后 HTTP协议就是解析这些电报让收到数据的一方能够读懂发送方发送的信息


②请求协议
Ⅰ请求数据格式


还有一个叫做请求体的东西:


小结:

Ⅱ请求数据获取


示例代码:
package com.mclzyun;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RequestController {
@RequestMapping("/request")
public String request(HttpServletRequest request) {
// 1. 获取请求方式
String method = request.getMethod();
System.out.println("请求方式: " + method);
// 2. 获取请求的URL
StringBuffer requestURL = request.getRequestURL();
System.out.println("请求URL: " + requestURL);
String uri = request.getRequestURI(); //request.getRequestURI() 获取请求的URI
System.out.println("请求URI: " + uri);
// 3. 获取请求协议
String protocol = request.getProtocol(); // HTTP/1.1
System.out.println("请求协议: " + protocol);
// 4.获取请求参数 - name, age
String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println("请求参数 age: " + age);
System.out.println("请求参数 name: " + name);
// 5.获取请求头 - Accept
String accept = request.getHeader("Accept");
System.out.println("请求头 Accept: " + accept);
return "OK";
}
}当我们访问地址:http://localhost:8080/request?name=zhenjing&age=18(内网)

小结:

③响应协议
Ⅰ响应数据格式
有一个请求就会有一个响应,响应的话和请求一样都分成了三个部分:


解释一下重定向(3xx响应码):

当你使用HTTP协议访问百度的时候会发生重定向(http://baidu.com)重定向到哪里?到HTTPS协议



上小结:

Ⅱ响应数据设置


示例代码:
package com.mclzyun;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
public class ResponseController {
// 方式一:httpServletResponse 设置响应数据
@RequestMapping("/response")
public void response(HttpServletResponse response) throws IOException {
// 1. 设置响应状态码
response.setStatus(201); // 201 表示资源创建成功
// 2. 设置响应头
response.setHeader("name", "McLzyun");
// 3. 设置响应体
response.getWriter().write("使用 HttpServletResponse 设置响应数据成功!");
}
@RequestMapping("/response2")
public ResponseEntity<String> response2(){
// 方式二:使用 ResponseEntity 设置响应数据
return ResponseEntity
.status(401) // 设置响应状态码为 202 Accepted
.header("name", "McLzyun") // 设置响应头
.body("使用 ResponseEntity 设置响应数据成功!"); // 设置响应体{
}
}
上小结:

4、SpringBootWeb案例
开发Web程序,完成用户列表的渲染展示

现在的主要任务是将HTML作为前端页面来展示用户列表数据,后端交给Spring来进行处理,使Spring把后端的数据以JSON格式的形式发送给前端
我们要进行两大前提操作:

那我们就开始创建项目,创建项目和前面差不多,只需要额外勾选Lombok这个依赖:

基本文件结构都有了:

我们手头上有用户列表文件,需要放在resource:(Main里面是程序文件 resource是资源文件)

再把黑马程序员给的HTML文件丢进去:

总体文件结构:

UserController:
package com.mclzyun.controller;
import cn.hutool.core.io.IoUtil;
import com.mclzyun.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController // @ResponseBody + @Controller -> 作用:将方法的返回值转换成json字符串响应给浏览器
public class UserController {
@RequestMapping("/list")
public List<User> list() throws Exception{
// 1.加载并读取user.txt 文件,获取用户数据
InputStream in = UserController.class.getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
// 2.将用户数据进行解析,封装成User对象 -> list 集合
List<User> userList = lines.stream().map(line -> {
String[] fields = line.split(",");
Integer id = Integer.valueOf(fields[0]);
String username = fields[1];
String password = fields[2];
String name = fields[3];
Integer age = Integer.valueOf(fields[4]);
LocalDateTime updateTime = LocalDateTime.parse(fields[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new com.mclzyun.pojo.User(id, username, password, name, age, updateTime);
}).collect(Collectors.toList());
// 3.将list集合转换成json字符串返回
return userList;
}
}User:
package com.mclzyun.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
private LocalDateTime updateTime;
}上小结:

5、分层解藕

➀三层架构




// 1.加载并读取user.txt 文件,获取用户数据
InputStream in = UserController.class.getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());这部分查询用户数据这部分要放在Dao当中
示例代码:
com.mclzyun.controller.UserController.java:
package com.mclzyun.controller;
import cn.hutool.core.io.IoUtil;
import com.mclzyun.pojo.User;
import com.mclzyun.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController // @ResponseBody + @Controller -> 作用:将方法的返回值转换成json字符串响应给浏览器
public class UserController {
private UserService userService = new com.mclzyun.service.impl.UserServiceImpl();
@RequestMapping("/list")
public List<User> list() throws Exception{
// * // 1.加载并读取user.txt 文件,获取用户数据
// InputStream in = UserController.class.getClassLoader().getResourceAsStream("user.txt");
// ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
// // 2.将用户数据进行解析,封装成User对象 -> list 集合
// List<User> userList = lines.stream().map(line -> {
// String[] fields = line.split(",");
// Integer id = Integer.valueOf(fields[0]);
// String username = fields[1];
// String password = fields[2];
// String name = fields[3];
// Integer age = Integer.valueOf(fields[4]);
// LocalDateTime updateTime = LocalDateTime.parse(fields[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// return new com.mclzyun.pojo.User(id, username, password, name, age, updateTime);
// }).collect(Collectors.toList());
// * // 3.将list集合转换成json字符串返回
// 1.调用service 获取用户信息
List<User> userList = userService.findAll();
// 2.返回数据
return userList;
}
}com.mclzyun.dao.impl.UserDaoImpl:
package com.mclzyun.dao.impl;
import cn.hutool.core.io.IoUtil;
import com.mclzyun.controller.UserController;
import com.mclzyun.dao.UserDao;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class UserDaoImpl implements UserDao {
@Override
public List<String> findAll() {
// 1.加载并读取user.txt 文件,获取用户数据
InputStream in = UserController.class.getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
return lines;
}
}com.mclzyun.dao.UserDao.interface:
package com.mclzyun.dao;
import java.util.List;
public interface UserDao {
public List<String> findAll();
}com.mclzyun.com.pojo.User.java:
package com.mclzyun.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
private LocalDateTime updateTime;
}com.mclzyun.service.impl.UserServiceImpl.java:
package com.mclzyun.service.impl;
import com.mclzyun.dao.UserDao;
import com.mclzyun.dao.impl.UserDaoImpl;
import com.mclzyun.service.UserService;
import com.mclzyun.pojo.User;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public List<User> findAll() {
// 1.调用Dao 获取数据
List<String> lines = userDao.findAll();
// 2.将用户数据进行解析,封装成User对象 -> list 集合
List<com.mclzyun.pojo.User> userList = lines.stream().map(line -> {
String[] fields = line.split(",");
Integer id = Integer.valueOf(fields[0]);
String username = fields[1];
String password = fields[2];
String name = fields[3];
Integer age = Integer.valueOf(fields[4]);
LocalDateTime updateTime = LocalDateTime.parse(fields[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new com.mclzyun.pojo.User(id, username, password, name, age, updateTime);
}).toList();
return userList;
}
}com.mclzyun.service.UserService.interface:
package com.mclzyun.service;
import java.util.List;
import com.mclzyun.pojo.User;
public interface UserService {
// 查询用户信息
public List<User> findAll();
}
上小结:

➁IOC与DI入门
Ⅰ介绍


上小结:

Ⅱ入门

那如何实现IOC容器管理呢?

只需要添加@Component 即可
第二步呢?添加@Autowired下面即可

这样的话他可以自己在容器中找到定义的对象并且赋值给紫色文字的那玩意,这样就完成了分层解藕
来看代码演示:



接下来完成依赖注入


上小结:
