ajax的学习
案例文档
码云
思维导图
语雀文档
Ajax
什么是ajax
- 一种由 浏览器 发起向 服务器 数据交互的技术
- 全称是 Asynchronous Javascript And XML 翻译为 异步 js 和 xml
同步&异步(晚上看视频)
同步是一种阻塞方式的代码执行过程
异步是一种非阻塞方式的代码执行过程如 ajax、setInterval、setTimeout
//同步的执行结束才会直执行异步程序
console.log(0);
setInterval(() => {
console.log(2);
}, 1000);
console.log(1);
- 执行结果:
![image-20220517133903499]()
XML(晚上看视频)
一种类似html的数据格式,表示 数据是以 xml格式 在服务器和浏览器上进行传输的。 网络传输数据的格式可以大概理解为
- XML
- JSON目前的主流方式
XML:
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
JSON
- 目前的主流方式
- JSON是一种类似对象的字符串
- son 的全称为:JavaScript Object Notation,是一种轻量级的数据交互格式
"{"name":"菜鸟教程","url":"www.runoob.com","slogan":"学的不仅是技术,更是梦想!"}"
请求和响应
- 谁请求?
- 浏览器负责发起请求
- 谁响应?
- 服务器负责响应数据
发起ajax的三大关键
- 请求地址
- 请求方式
- 不考虑规范两种
- 考虑规范:五种

- 请求参数

发起地址(问后端要)
- 请求地址主要是由后端程序员提供给前端工程师的使用的。 一般会通过文档的方式来告诉前端。
- 目前图书案例文档地址:
发起请求(看后端给的文档)
发起ajax的5种方式
| 序号 | 请求方式 | 描述 |
|---|---|---|
| 1 | POST | 向服务器新增数据 |
| 2 | GET | 从服务器获取数据 |
| 3 | DELETE | 删除服务器上的数据 |
| 4 | PUT | 更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息) |
| 5 | PATCH | 更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号) |
请求参数(不是必须 看文档说明)
- 某些数据,必须要传递给服务器,才能成功获取到对应的数据
- 做注册时,你不传递个人信息给服务器,服务器无法办法登记你信息完成注册
- 做查询数据时,查询华为手机,你不传递如型号、价格、配置,服务器也无法给你返回合适的数据
工作中使用ajax的方式
axios
GET请求不带参数
<script src="./lib/axios.js"></script>
<script>
// 请求地址 http://www.itcbc.com:3006/api/getbooks
// 请求方式 GET
// 请求参数 可以不传(文档写的)
axios({
url:'http:www.itcbc.com:3006/api/getbooks',
method:'GET',
}).then(function(result){
// console.log(result);
console.log(result.data.data);
})
</script>
GET请求带参数(参数可以显示在url上)
方式一:写在url上
格式:url + ?+ 条件
- 多个条件就在条件中间增加
&
axios({
url:'http:www.itcbc.com:3006/api/getbooks?bookname=斗破苍穹134',
method :'get',
}).then(result=>{
// console.log(result);
console.log(result.data.data);
})
方式二:准备一个params对象
格式:params{ 条件 }
特点:浏览器会根据方式二转化为方式一,在浏览器中的network中查看
axios({
url:'http:www.itcbc.com:3006/api/getbooks',
method:'get',
params:{
//要携带的请求参数
bookname:'西游记',
author:'吴承恩',
}
}).then(result=>{
console.log(result.data.data);
})
POST请求方式(url上无法看见参数)
- 新增数据
axios({
url:"http://www.itcbc.com:3006/api/addbook",
method:"POST",
data:{
bookname:"从入门到出去",
// bookname:"1",
author:"黑马77",
publisher:"白马",
// appkey:"sdfr34343"
}
})
.then(result=>{
console.log(result);
})
dele请求方式
- 删除数据
查看文档,文档要求传送的数据
axios({
url: 'http://www.itcbc.com:3006/api/delbook',
method: 'DELETE',
params: {
appkey: 'sdfr34344',
id,
}
}).then(result => {console.log(result.data.message); })
put请求方式
- 修改全部数据,传输的参数如下所示:

axios({
url: 'http://www.itcbc.com:3006/api/updatebook',
method: 'PUT',
data: {
bookname: booknameValue,
author: authorValue,
publisher: publisherValue,
appkey: "sdfr34344",
id,
}}).then(result => {
console.log(result.data.message)
})
如何区分不同的请求方式携带参数写在data还是params
-
看文档
Query 参数 url上或者params上 body 参数 data -
默认
1 get请求 url或者params 2 post请求 data 3 delete、put、patch 结合文档来看 1 delete 和 get 类似 2 put patch post 类似 -
试试就知道了
day2
1、动态元素的事件绑定一定要用到事件委托
- 以前生成动态结构使用的是for循环,这是同步事件,所以我们可以等他生成好了下一步绑定它,但是先我们生成动态结构是在axios里面,这是异步事件,下面获取是doc.qs是同步事件,同步快于一同出结果,所以doc.qs获取不到结果。
表单
表单按钮
<!--
点击按钮的时候 网页 以为你要做 整页数据提交 (在ajax出现之前 前端向后端提交数据的方式!! )
1 如果按照提交数据给服务器来说 现在的前端 不需要用到 form表单和input标签的name属性
2 如果网页的表单 input特别多 form表单和name有另外一个作用 可以快速来获取表单的数据
3 解决 form表单和按钮在一起刷新的问题
1 type="button" 方式1
2 刷新 是form 的默认行为 - 阻止 默认行为 方式2
1 form 有一个事件 submit 吗 (当页面执行提交数据)
-->

<form>
<input type="text" name="">
<input type="password" name="">
<!-- 什么都没有,只有button就会默认刷新 -->
<button>登录</button>
<!-- 添加了type="button",input提交不能刷新 -->
<input type="button" value="也是提交,但不刷新">
<!-- 不是type="button",保持刷新了 -->
<input type="submit" value="也是提交,但刷新">
</form>
<script>
const form = document.querySelector('form');
// 为了解决这个点击刷新的问题,可以统一给表单form添加禁止默认行为
//配合submit事件
form.addEventListener('submit',function(e){
//这个下去以后,其他都不用设置了
e.preventDefault();
console.log('表单提交但是不刷新');
})
</script>
data字符串格式数据
-
由于aixos的data由两种传值模式:
- 对象模式
- 字符串格式
-
引入的背景:是为了获得提单表单元素的值做准备的

axios({
url: 'http://www.itcbc.com:3006/api/addbook',
method: 'POST',
// data: {
// bookname: '演示',
// author: '我自己你不知道',
// publisher: '斑马出版社',
// appkey: 'bbccddaaa',
// },
data: 'bookname=演示&author=我自己你不知道&publisher=斑马出版社&appkey=bbcc33aaa',
}).then(result=>{
console.log(result);
})
快速获取form表单中inpput(name属性)
jq方式获取
步骤:
- 引入jq文件
$('获取到的表单元素').serialize();
代码:
<script src="./lib/jquery.js"></script>
<script>
const form = document.querySelector('form');
form.addEventListener('submit', function (e) {
e.preventDefault();
const query = $('form').serialize();
console.log(query);
})
</script>
效果:

注意事项:
- 首先是必须要添加form表单,没有的话
$('form')就获取不到 - 其次表单元素input一定要添加name属性,不然字符串无法拿到
原生js快速获取表单的值
- 借助两个新对象的帮助
- FormData() //高频
- 快速获取form标签中表单的值
- 文件上传
- URLSearchParams()
- FormData() //高频
FormData
FormData
1 FormData 构造函数 可以new 出一个实例
2 FormData 可以存放一些数据的实例(不像普通的obj)
3 调用方法 append(key,value) 添加数据
4 FormData 不像普通的对象 可以直接打印看数据 它比较害羞 打印 它
1 通过 forEach 方法来遍历 FormData 挨个来查看里面的数据
注意点:
- formData虽然是构造函数,可以new出一个实例,但是,这个实例并不是普通的对象,他无法直接打印输出

效果:
- 可以存放数据,但因为不是普通对象,不建议用点方法新建属性,必须通过append()添加

- 虽然不是数组,但查看属性值属性名使用foreach遍历获取

效果:
使用ForData快速获取表单的数据
步骤:
- 添加提交事件,在事件里面用ForData new一个对象(但不是普通对象)出来
- 将form的dom元素放入参数中
const fd = new FormData(form)
代码实现:
const form = document.querySelector('form');
form.addEventListener('submit', function (e) {
e.preventDefault();
// const fd = new FormData(form);
const fd = new FormData(this); //获得了form表单带有name属性的值
fd.forEach((v, k) => {
console.log('属性名 :', k);
console.log('属性值:', v);
})
})
效果:

缺点:
-
还无法使用,无法发送给后端
-
后端要的数据data是两个格式
-
对象data
![image-20220520001619154]()
-
字符串data
![image-20220520001730805]()
-
-
因此FormData对象获取的数据还需要进一步加工,实现效果如右图所示

处理FormData获取的数据
方式一:拼接字符串
<form>
<input type="text" name="username" value="111" />
<input type="text" name="password" value="222" />
<button>获取数据</button>
</form>
<script>
const form = document.querySelector('form');
form.addEventListener('submit', function (event) {
event.preventDefault();
// const fd=new FormData(传入一个form的dom元素);
// const fd=new FormData(form);
const fd = new FormData(this);
const list = [];
fd.forEach((value, key) => {
list.push(`${key}=${value}`);
});
// console.log(list);
});
</script>
方式二:URLSearchParams
<form>
<input type="text" name="username" value="111" />
<input type="text" name="password" value="222" />
<button>获取数据</button>
</form>
<script>
const form = document.querySelector('form')
form.addEventListener('submit',function(){
event.preventDefault();
const fd = new FormData(this)
const usp = new URLSearchParams(fd)
const query = usp.toString()
console.log(query);
})
// 可以封装成函数
function toQuery(form) {
const fd = new FormData(form);
const usp = new URLSearchParams(fd);
const query = usp.toString();
return query;
}
</script>
axios简写方式
- get请求简写方式
- 极其要注意get参数params要用
{}包起来,而params本身也是一个对象
aixos.get('url',{params}).then(result=>{console.log(result.data.data)});
//示例正确写法
axios.get('http://www.itcbc.com:3006/api/getbooks', {
params: { appkey: 'bbccddaaa' },
}).then((result) => {
console.log(result);
});
- post简写方式
- 如果不简写,post的参数传输使用的是data对象,post简写时候无需额外写data,直接将值放入{}中
axios.post('url',{参数}).then(re=>{console.log(re)});
//正确示例
axios.post('http://www.itcbc.com:3006/api/addbook', {
bookname: '演示ttt',
author: '我自己你不知道ttt',
publisher: '斑马出版社ttt',
// 改为只有自己知道的key 长度 6-20
appkey: 'bbccddaaa',
})
.then((result) => {
console.log(result);
});
定义基地址
- 简写配合基地址
<script src="./lib/axios.js"></script>
<script>
axios.defaults.baseURL = 'http://www.itcbc.com:3006';
axios.get('/api/getbooks',{params:{
appkey:'sdfr34344',
}}).then(re=>console.log(re.data.data)
)
axios.post('/api/addbook',{
bookname:'西游记',
author:'吴承恩',
publisher:'北京出版社',
appkey:'sdfr34344',
}).then(re=>console.log(re.data.message)
)
axios.delete('/api/delbook',{params:{
id:17661,
appkey:'sdfr34344',
}}).then(re=>console.log(re.data.message)
)
axios.put('/api/updatebook',{
id:17688,
bookname:'西游记',
author:'吴承恩',
publisher:'南京出版社',
appkey:'sdfr34344',
}).then(re=>console.log(re.data.message)
)
效果:
上传图片
使用file上传
两个步骤:
-
把图片文件加载到浏览器 显示出来(不需要后端)
-
指定一个
input标签类似file -
给
input标签绑定一个change事件 -
通过
this.files来获取到文件this.files是数组 -
在网页中显示一张图片 只需要获取到图片的地址即可
⭐由于图片还放在内存中,想要把图片显示在页面上话还需要获取到图片存放的地址 获取内存中图片的地址:URL.createObjectURL(想要获取的内存地址) 注意:只能拿一个文件的地址,如果有多个,遍历即可
-
使用formData发送给服务器
-
使用formData进行文件的上传(发送到服务器)
-
FormData有两个作用(1 快速获取表单的数据 2 文件上传)
-
使用FormData的
append来包装文件const fd = new FormData(); //属性名需要查看文档!!! fd.append('属性名',this.files[0]);![image-20220521170044549]()
![image-20220521170152591]()
-
实现代码:
const input = document.querySelector('input');
const img = document.querySelector('img');
input.addEventListener('change',function(){
const url = URL.createObjectURL(this.files[0]);
img.src = url;
const fd = new FormData();
// fd.append('avatar',文件);
fd.append('avatar',this.files[0]);
// 本来应该在里面放入参数{ 属性名:属性值}对象,但fd是构造函数new出来的对象,就可以直接塞进去了
axios.post('http://www.itcbc.com:3006/api/formdata',fd).then(re=>console.log(re.data.message)
);
})
day03
接口-API文档
- api文档:后端针对某个项目编写提供数据的文档
请求报文&响应报文
请求报文
- 请求行
可以知道用的什么请求方式

- 请求头部
- 请求体
我们传输过去的参数

- 空行
响应报文
组成部分:状态行、响应头部、空行、响应体(返回的数据message)
http响应状态码
通用状态码:检查错误的来源

常见状态码含义:
- 一般是后端写的,类似前后端通讯的一套暗号

http 响应状态码 vs 业务状态码
位置不同
- 这是响应状态码的位置:打开network面板就能看见

- 这是业务状态码的位置:要点击进入请求查看后端返回状态

通用性不同
- 响应状态码是行业通用,含义是一样的
- 业务状态码根据项目、公司规定改变而可能发生不同,非行业通用
表示结果不同
- 响应状态码只能表示这次请求的成功与否
- 业务状态码用力啊表示这次业务处理的成功与否
XMLHttpRequest & 跨域
XMLHttpRequest(简称XHR)
- 是浏览器内置的一个构造函数
使用XMLHttpRequest发起GET请求
步骤:
- 1 创建xhr实例
- 2 调用open方法(指定请求的类型和地址)
- 3 开始发送请求
- 4 监听 数据响应
<script>
// 1 创建 xhr 实例
const xhr = new XMLHttpRequest();
// 2 调用open方法 (指定请求的类型、指定请求的url)
xhr.open('GET', 'http://www.itcbc.com:3006/api/getbooks');
// 3 开始发起请求
xhr.send();
// 4 监听 数据响应
xhr.addEventListener('load', function () {
// 获取响应结果
console.log(this.response);//返回JSON字符串
// 本质上返回字符串类型是正确的
// axios别人封装的库, 别人帮我们重新把 JSON字符串 转成了对象而已
console.log(JSON.parse(this.response));//返回对象
});
效果:
使用原生ajax-get携带参数
- 不同于直接使用的axios,可以使用两种携带参数的方式:params和拼接到地址
- 原生只有拼接到地址这一个方式
const xhr = new XMLHttpRequest();
xhr.open('GET',"http://www.itcbc.com:3006/api/getbooks?bookname=人间不值得a");
xhr.send();
xhr.addEventListener('load',function(){
console.log(JSON.parse(this.response));
})
效果:
原生ajax-post发送
post 请求 传递的参数
- 只能放在 send中
- 传递的参数的格式 3种格式
- 字符串的形式
- a=1&b=2&c=3
- 可以直接使用usp数据格式
- json的格式
- FormData的格式
- 字符串的形式
方式一:字符串格式
const data = {
bookname: "从入门到出去",
// bookname:"1",
author: "黑马77",
publisher: "白马",
// appkey:"sdfr34343"
}
const usp = new URLSearchParams(data);
const query = usp.toString();//转化为字符串
console.log(query);
//使用原生ajax来使用post请求第一个方式:传入usp
const xhr = new XMLHttpRequest();
xhr.open('POST','http://www.itcbc.com:3006/api/addbook');
//1、这里为什么不用转化成字符串的query,而是直接写了usp,原因在于send()隐式转化了,将usp转化成了字符串
xhr.send(usp); //2、按道理放入query也可以,但是报错 xhr.send(query);
xhr.addEventListener('load',function(){
console.log(this.response);
})
(1)的效果:
(2‘’)的效果:
解决(2'')的方法:
// 正在解决2的问题
//设置请求头 告诉后端我们使用的是三种方式中的哪种
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
xhr.send(query); //成功
xhr.addEventListener('load',function(){
console.log(this.response);
})
效果:
请求头的类型:
问题
-
send()为什么可以使用usp?
- 打开MDN,检查接口使用的方法,里面就已经有,他是可以接收usp数据格式的
- 如果还是想传入toString后的字符串,
![image-20220520140701838]()
![image-20220520141026201]()
-
toString()拓展
方式二-JSON格式
- 更换请求头地址
- 将对象data转化为JSON字符串
const data = {
bookname: "从入门到出去",
author: "黑马77",
publisher: "白马",
}
const usp = new URLSearchParams(data);
const query = usp.toString();
console.log(query);
const xhr = new XMLHttpRequest();
xhr.open('POST','http://www.itcbc.com:3006/api/addbook');
xhr.setRequestHeader('content-type','application/json');
console.log(JSON.stringify(data));
xhr.send(data)//谷歌浏览器的网络面板的载荷显示[object object],直接丢了个对象进去在低层给我们隐式转化了,不符合请求头的格式(传入json数据格式),报500的错误
xhr.send(JSON.stringify(data));
xhr.addEventListener('load',function(){
console.log(this.response);
})
同学的案例代码:

day04
大案例:涉及了新的知识点
渲染函数
- 接收参数
- 如果参数为空,就直接渲染请求发送回来的数据
- 如果参数不为空,
查询图书
主要和渲染相关,我们想要的效果是:

- 给搜索添加点击事件
- 获取input框的value
- 然后调用渲染函数,传入参数:render(bookname)
新增图书
实现步骤:
-
1、为新增按钮添加点击事件
-
2、弹出模态框
-
3、获取模态框表单
- 3-1 为模态框表单添加submit事件
- 3-2 快速获取表单元素内容
- 3-3 发送post请求
- 3-3-1 成功重新渲染页面
- 3-3-2 重新设置表单内容(清空)
注意事项:
3、bootstrap开启模态框语法:$('模态框id').modal('show');

3-1、由于bootstrap中拷贝的模态框是吧表单form和button按钮分开写的,因此为了实现点击button也能获取表单值,我们将对两者进行联系:
- 对form:添加id属性

- 对button:修改type属性为
submit,添加form属性,取值为form表单中id属性的值一致

- 3-3-2 情况表单元素内容

修改图书
-
由于后端返回的是一个对象,遍历对象使用for in方法
-
for in的初次使用
- for in 与 for each区别

删除图书
总结
关闭表单历史输入提示
联系form和form外的按钮方式
联系的两个条件
关闭/开启模态框
自定义属性的写法(老是忘记“ ”)
简写的axios第二个参数的字符串传输写法
day05
加载进度条提示+axios拦截器
-
公共js文件中书写(没有看到怎粘贴的)
-
响应拦截器、请求拦截器
-
引入顺序出错的话,会发生先发送了请求,然后再设置拦截器,就晚了
![image-20220523093555041]()
-
基地址设置
也是放在common.js中设置,避免多个页面多次设置
使用Fetch
- 学习地址
- fetch和XMLHTTPRequest类似,就是fetch更简单
- 原生ajax
- 兼容性稳定性没有axios好,目前大型项目中依旧使用主流axios
<script>
fetch('http://www.itcbc.com:3006/api/getbooks').then(result=>{
return result.json();
}).then(result=>{
console.log(result);
})
</script>
跨域和同源
- 是浏览器的一种安全机制
- 不同源或者两个URL之间 默认不让你们做数据交互(不允许发送ajax请求)
- 是否同源的标准:
- 协议的名称-http\https
- 主机 / 域名 / ip地址 (www.baidu.com 和 www.qq.com)
- 端口号(www.baidu.com:1011 和 www.qq.com:1012)
如果原本两个公司合并了,想要将这两个去交互——解决跨域
- 后端解决
- CORS (Cross-Origin Resource Sharing)
- 前端解决
- jsonp script标签的src属性天生不跨域的特性解决
- 只能用get请求


防抖和节流
- 防抖
- 应用场景:搜索框
- 需求:用户输入完毕,自动发出请求
- 关键技术原理
- 实现过程:
- 每一次输入的时候:1 先清空上一次的延时器
- 2 再开启一个新的延时器
节流
- 上一个业务没有完成,不允许下一个业务结束
- 应用真实场景:获取验证码案例、倒计时
Git
安装git客户端
为什么要学习Git-版本管理软件
- 便于记录修改
- 便于多人协作开发
有哪些版本管理软件
-
集中式
svn老旧- 我们想要使用任何 版本管理 功能 都必须要连接上服务器 。 一旦服务器出现了问题, 代码记录都没有了。
-
分布式
Git主流 常用!!-
在每一个人的电脑上 都会存在 一个 版本库。我们想要提交记录、查看历史记录、都不需要用服务器。
当我们想要和同事 分享代码的时候,才需要连接一下服务器。
-
官网下载地址
-
https://git-scm.com/ 网址在国外 可能比较慢 自己百度关键字来下即可
-
git 腾讯软件
使用 git工具 来查看安装好版本
- 鼠标右键 空白目录

常见命令
初始化仓库:git init
设置个人信息
- 设置
- 邮箱
- 用户名
- 查看
查看git版本
git --version
添加到暂存区
提交到本地仓库
查看状态
-
查看状态:
git status -
精简:
git log --oneline -
强大:
git reflog
撤销
回退到任意版本:git reset --hard 版本号
远程仓库
克隆仓库
推送到远程仓库
拉取远程更新

分支
- 开启新分支
git branch 分支名字
- 查看分支
git branch
- 删除分支(一般领导专用)
git branch -d 分支名字
- 切换分支
git checkout 分支名字
- 合并分支(领导专用)
git merge 被合并的分支
-
将分支推送到远程仓库
- 先切换 分支
- 再在分支上 执行命令
git push --set-upstream 远程仓库别名 分支名字
-
注意事项
在哪新增、修改文件就在哪个分支上git add .
如果想要在其他分支添加文件、修改文件,就先切换分支,再对文件进行修改
忽略清单
其实是一个文件:.gitignore
-
文件下注释:
# -
文件下书写忽略文件以及文件夹:
1.js、.vscode/ -
注意:忽略清单要放置还没有创建的文件,如果写道一半要添加到清单,git不允许
大案例
准备工作
- 新增js文件
- 新增common.js
- 新建公共文件common.js
- 设置基地址
- 设置加载+拦截器
- Nprogress引入css
- Nprogress引入js,在common之前
- 新建公共文件common.js
- 新增login.js
- 引入到login.html页面
- 为了测试拦截器,书写一段axios
- 新增common.js
登录注册页面
面板切换
- 到达login.js文件
- 获取去登录、去注册 a链接
- 去login.html添加a标签的类名
- 获取登录、注册面板
- 给a标签分别注册点击事件
- 注册则隐藏登录,显示注册面板’
- 登录则隐藏注册,显示登录面案
- 获取登录、注册面板
- 获取去登录、注册 a 链接
- 注册点击事件
- 对应切换、隐藏面板
点击登录跳转
为表单添加提交事件
- 如何处理业务状态码给拥护反馈?
- 在请求(axios)结果中处理
- 如何处理http状态码的错误给拥护?
- 在拦截器(NProgram)中处理


根据老师的思想,他先找到了拦截器,并打印出了拦截器的错误
代码:common.js

一顿展开后:
可以看到,在response的data的message里面有提示400错误的提示信息:

因此,老师就顺着思路下去,让我们打印出这个错误的提示信息:
到这里就简单了,只需要使用toastr已经封装好的代码 toastr.error()将信息放进提示框中
token
- 携带过去才能使用其他接口
- token存放在 请求头
- 请求标头(对象 属性 属性值)
- 在请求中添加请求标头(放在params的位置)就是带着taken去发请求才有用
- 注意书写格式
{headers:{配置参数:本地取出的taken值}} - 注意 headers 要小写
首页index
引入


退出登录
- 给退出按钮添加点击事件
- 询问用户的是否确定退出,如果确定:
- 清除本地存储的token
- 跳转回登录页面
获取登录用户的信息
- 查看接口文档( 文档找不到=》询问后端:没完成 先跳过)
初始化数据
该功能在正常项目中不存在
实现是为了锻炼
- 获取初始化按钮
- 绑定点击事件
- 接口文档=》初始化数据接口
- 发送请求
- 为了验证身份,发送这个请求
左侧菜单功能
一级目录展开
首先要理清页面的结构:
- 找到二级标题被隐藏的原因:index.css中对 所有nav 下的ul 进行了 隐藏 (display:none)

- 所以我们分析,如果给ul 添加上一个类 可以显示ul,就能做到展开了
- =》 所以我们也在index.css里面添加了展示的属性:
![image-20220526140423420]()
- 接下来,我们要 实现 点击一级目录展开二级目录的需求:
- 如果是展开状态(block),点击就会收起(none)
- 如果收起(none),点击就会展开(block)
- 使用classList.toggle实现需求
- =》 所以我们也在index.css里面添加了展示的属性:
//获取一级列表的两个a标签
const topList = document.querySelectorAll('.nav>li>a');
//遍历添加点击事件
topList.forEach(aDom => {
console.log(aDom);//侧边栏的俩个一级分支的a标签
aDom.addEventListener('click', function () {
// 点击就切换类,有就移除,没有就添加:toggle
//是给一级目录a标签的 藏着 图标概览 和 学员信息|成绩录入 的二级标签显示用的
this.nextElementSibling.classList.toggle('show');
})
})
二级目录选中状态
- 我们可以看到,页面一打开又是可以自动展开并且“图标概览"有一个激活active的样式
- 这个样式存在于
.nav 的 li 标签的a标签中 - 因此我们在这个一开始就给这个标签添加上active这个类

- 因此我们就要先获取全部的二级列表的a标签
- 遍历添加点击事件
- 使用排他思想
const SecondList = document.querySelectorAll('.nav ul a');
// const SecondList = document.querySelectorAll('.nav ul li');//error 检查元素,是li 里面的a添加了active类
SecondList.forEach(ADom => {
ADom.addEventListener('click', function () {
//排他思想
document.querySelector('.nav ul a.active').classList.remove("active");
this.classList.add("active");
})
})
token权限开启操作——请求头的添加
- 背景:如果没有token,除了登录和注册以外的所有请求都不应该被响应
- 因此先判断进来index操作的人是否携带了token
- 如果携带了,就在响应发送的请求头中添加
authorization- authorization不是固定不变的,是需要由接口文档进行取值,但是这个项目没有写,老师取值是先查询文档,后按照默认值authorization尝试
- 这个操作使请求发起简易化,在拦截器发起请求前先设置请求头的话,下次再发送请求就不需要再设置请求头了

token权限开启操作——响应错误的操作
- 背景:对于没有携带token的用户想要跳过登录注册操作直接跳转到index的行为应该进行阻止
- 对于没有登录想要直接跳转的行为,我们应该将它直接强行跳转到登录页面

修改学生成绩功能
引入
打开页面,显示成绩数据
- 定义一个函数,发送请求获取数据
- 对数据遍历,生成htm标签,显示在页面中
双击表格进行修改
- 给目标元素先绑定好 双击(短时间内快速按两下鼠标)事件
- 在对应的
td中 显示 出来输入框 - 用户在输入框中数据的填写,触发 输入框 失去
焦点事件 - 获取用户最新的输入,拼接成参数 发送给后端,完成数据的修改
学员管理功能
查询
删除
- 事件委托获取删除按钮
- 删除按钮添加自定义属性
- 获取id,根据id发送删除学员请求
- 成功重新渲染页面
- 弹出提示框
新增
打开模态框方法
-
jq方法
-
html标签添加
<button type="button" class="btn btn-primary btn-sm modal-dialog-centered addStu" data-bs-toggle="modal" data-bs-target="#addModal">添加学员</button>

-
省市区联动
-
省的获取
- 直接发送请求,将获取到的数据写入省的select
- 使用字符串拼接,保留省的默认值
axios.get('/geo/province').then(res => { // console.log(res.data); const provinces = res.data; let provinceStr = '<option selected value="">--省--</option>'; provinceStr += provinces.map(value => { return `<option value="${value}">--${value}--</option>` }).join(''); addProvinceSelect.innerHTML = provinceStr; }) -
市的获取
- 看接口文档,要求获取市需要传入 省 的参数进行匹配
- 获取用户选择省的数据使用的是
change事件,监听 省 的内容变化
// 获取市 监听省的列表变化 addProvinceSelect.addEventListener('change', function () { // 重置省时 区要回到默认值 addCountySelect.innerHTML = '<option selected value="">--区--</option>'; const pname = this.value; // console.log(pname); axios.get('/geo/city', { params: { pname } }).then(res => { // console.log(res.data); const citys = res.data; console.log(citys); let cityStr = '<option selected value="">--市--</option>'; cityStr += citys.map(value => { return `<option value="${value}">--${value}--</option>` }).join(''); // console.log(cityStr); addCitySelect.innerHTML = cityStr; }) }) -
区的获取
-
查看接口文档,需要传入 省、市 两个参数
-
监听 市 内容的变化
// 获取区 监听市的列表变化 addCitySelect.addEventListener('change', function () { const pname = addProvinceSelect.value; const cname = this.value; console.log(pname, cname); axios.get('/geo/county', { params: { pname, cname } }).then(res => { console.log(res.data); const countyList = res.data; console.log(countyList); let countyListStr = '<option selected value="">--区--</option>'; countyListStr += countyList.map(value => { return `<option value="${value}">--${value}--</option>` }).join(''); addCountySelect.innerHTML = countyListStr; }) })
-
-
切换省,市、区都要返回默认值(就是
--市--、--区--)![image-20220528112055064]()
效果:
![image-20220528112230892]()
-
重置按钮的漏洞
-
原本:写在button的属性上
![image-20220528112321689]()
-
问题:可以重置其他表单信息为空字符串(
value=''),但是下拉列表的历史记录依旧存在,我们想要做到用户点击重置以后,表单的省保留,市、区全部回到默认值,没有其他选项

- 解决:添加表单重置事件对市、区进内容重置


新增学员
- 点击 确认添加
- 触发表单的提交事件
submit触发 - 阻止默认行为(刷新页面)
- 使用jq的方法 快速获取表单的数据
- 根据接口文档的要求 发送 添加学员请求
- 添加成功
- 关闭模态框
- 重置表单
- 弹出提示信息 提示用户
- 刷新页面数据
- 触发表单的提交事件
修改
普通表单值和单选框值的传入
-
普通输入框的数据填入
-
直接使用请求回来的对象数据进行for in遍历
-
将对象值写入输入框中
-
循环过程中跳过单选框的写入 以及 跳过doc.qs找不到的元素(原因:单选框不是使用value值进行设置,而是checked进行设置,因此要单独剥离出来)
for (const key in stuObj) { const dom = document.querySelector(`#updataForm [name=${key}]`); console.log(dom); // 遍历到性别直接退出 if (key === 'sex' || !dom) { continue; } // 其他直接写入 dom.value = stuObj[key]; }
-
-
单选框的数据填入
-
写在for in 循环外面,单独开业务,循环里是给表单设置value值有效写的
-
搜索 单选框 性别与请求回来的值相对应 的dom元素修改checked值
原始版本:
![image-20220528203940262]()
精简版本:
// 性别的修改写在循环外面 因为性别修改的不是value值而是checked属性 //在updataForm表单里搜索属性为name=sex且value值为stuObj.sex的元素(使用的交集选择器) updataForm.querySelector(`[name=sex][value=${stuObj.sex}]`).checked = true;
-
同步学员的籍贯信息
-
背景:我自己之前写的案例出现只能传入省份无法传入其他两个地区的原因在于:设置市的信息时,市的下拉列表还没有出现,因此无法使用value进行匹配
-
在委托的点击事件的请求发送成功中写入 市区的同步信息
![image-20220528205602476]()
-
![image-20220528205907865]()
Echart
网站
初次使用
可以进入官网后点击快速入门,把代码拷贝下来
- 要放入表格的dom元素选择器
- 表格信息option
- 指定配置项和数据显示图标语句

折线图(图表知识点多)
- 本次案例使用的折线图案例:

- 简单代码示意

-
最重要的就是series,因此我们需要给series赋值
-
首先处理获取学员信息传进来的数组
![image-20220529122127588]()
-
需要拿到学员名字、学员薪资、真实薪资,因此需要处理出三组数据(使用map,将处理成功的数据以数组返回)
![image-20220530154531537]()
-
处理成功则传入给折线图的series里面的两条折线
-

额外的知识点:
-
注意这写参数放的位置
-
如何设置折现图曲线变成平滑曲线?
![image-20220530155025583]()
-
如何设置线条颜色?
![image-20220530155042997]()
-
如何设置折线图底部拖拽条
![image-20220530155108176]()
柱状图(两个y轴)
选用的官网柱状图:
选用原因:和参考项目比对,发现有左右两个y轴,因此选用

-
在官网中先把我们要的图形处理干净再拿过来vscode中使用
![image-20220530155751597]()
-
现在我们的项目要求:
-
点击点点可以出现不同组别,再次点击就可以收回组别信息
![image-20220530160221961]()
-
点击组别可以出现不同组的折线图效果
-
首先解决请求不同组别成绩的问题
- 阅读接口文档
- 要求传入batch组别参数
![image-20220530160549503]()
代码:
![image-20220530160654665]()
- 将组别参数传给渲染柱状图
![image-20220530160741106]()
-
-
-
渲染柱状图详情


其他数据同理:

-
额外知识点:
-
如何解决图表大小的问题?
grid对象![image-20220530164055412]()
-
玫瑰图(处理数据较难)
- 背景:想要获得渲染玫瑰图需要的数据

- 但是现在我们获取到的数据长这样:

-
其实就是拿出arr中的一个数据(省份),让这个数据和新数组newArr中的数据进行对比,如果对比结果是成立,那就是新数组中已经存在这个省份,那只需要让value++
![image-20220530164840846]()
-
如果没有,就设置出现省份的数量为1,以及添加这个省份
![image-20220530164855201]()

地图(难)
地址:交流社区
地图地址:使用案例的地图
配置解释
代码书写
-
使用地图会出现跨域的错误
-
跨域的解决方案
-
jsonp 前端自己扒数据使用
-
![image-20220531100955967]()
![image-20220531100842978]()
![image-20220531101433212]()
-
数据的地址
- 调试找到请求(记得阻止所有断点)
![image-20220531093444178]()
-
新建js页面,用于放置扒下来的数据
-
一些补充
JWT
json web token 就是我们使用的令牌 token
注释折叠
vscode的js可以折叠代码(随便写哪个)

iframe标签和a标签
iframe
- 可以实现 页中页 效果
- 父子页面不共享js和css等静态资源
- iframe标签经常和a标签相搭配。 a标签的target 属性 要等于 iframe标签的name属性
- iframe标签 添加一个属性 name
- a标签 target = iframe name属性
<a href="./02-son.html" target="view" >02</a>
<a href="./03-.html" target="view" >03</a>
<a href="./04-.html" target="view" >04</a>
<iframe src="" name="view" frameborder="0"></iframe>
- 效果:
![image-20220526200827249]()
案例应用场景:
下面就是页中页的跳转出现的bug,原因在于父页面(index)里面使用了iframe,子页面(bashboard)中跳转到 login ,时子页面的范围内跳转,因此无法全页面跳转

- 解决方法:
子页面想要跳转全页面使用的方法是:window.top.location.href(common.js)

- 缺点:工作基本不用


































浙公网安备 33010602011771号