Ajax
服务器相关的基础概念
服务器
服务器的本质:也是一台电脑。
服务器的作用:
存储一个网站的文件(HTML、CSS、JS、图片、音乐.....)
提供网站的文件给用户
如何获得服务器
购买(京东、淘宝……)
租赁(阿里云、腾讯云……)
资源
服务器上的 网页(html文件)、图片、音乐、视频、字体文件、CSS文件、JS文件等等都称之为资源。所以资源代指服务器上存储的内容。
通俗的讲,我们浏览网页时,从网络当中看到的内容都叫做资源。
数据也是资源
网页中的数据,也是服务器对外提供的一种资源。例如股票数据、各行业排行榜等。
数据
服务器多数情况都使用数据表的方式来存储数据,和我们平时见到的表格差不多,形式如下:
客户端
概念:在前端开发中,客户端特指“Web 浏览器”。
作用:将互联网世界中的 Web 资源加载、并呈现到浏览器窗口中供用户使用。
最常见的“客户端浏览器”都有哪些:
URL 地址(统一资源定位符)
服务器上的每个资源,都对应着独一无二的URL地址
数据也是服务器上的资源
对数据的操作增删改查,也对应着不同的URL地址
示例
<script>
/*
想要获取服务器上的数据 url ,它是后端程序员提供
http://www.itcbc.com:3006/api/getbooks 图书数据
我们需要通过代码的方式 把服务器上的数据 变成 一个普通的变量 数组
给我数组了 我就懂得如何去页面渲染了 第三方的一个js的帮助
axios
1 下载 引入到项目中
2 根据url的地址 来编写代码
1 获取数据 -get ( 请求类型 1 get 2 post 3 delete 4 put 5 patch )
2 编写代码
*/
// 开始向服务器 发送请求 索要数据
axios({
// method:"请求类型",
// url:"资源地址",
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks',
}).then((result) => {
// 如果这个代码可以触发 数据回来了
// console.log(result); // 服务器给我们返回的数据!!
// 数组数据
// 给你了一个数组 arr 数组的格式
const arr = result.data.data; // 字段的名称 id、bookname、author。publisher 固定
// console.log(arr);
// 你 有能力 根据 数组 来 显示到页面中
render(arr);
});
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
客户端与服务器通信的过程
就像我们(客户)去银行(服务场所)办理业务:
客户提出需求:客户提出要办理业务,比如办卡、存钱、取钱、销户、买纪念币等等
银行的回应:银行根据客户的需求,办理相关的业务
客户端与服务器之间的通信过程,分为请求 - 响应两个步骤。其中:
请求的概念:客户端通过网络去找服务器要资源的过程,叫做“请求”
响应的概念:服务器把资源通过网络发送给客户端的过程,叫做“响应”
什么是 Ajax
Ajax 是浏览器中的技术:用来实现客户端网页请求服务器的数据。
它的英文全称是 Asynchronous Javascript And XML,简称 Ajax。
网页中 Ajax 的应用场景无处不在,有数据的地方就有 Ajax!
请求方式
使用 Ajax 请求数据的 5 种方式
Ajax中,客户端浏览器在请求服务器上的数据时,根据**操作性质(增删改查)**的不同,可以分为以下 5 种常见的操作:
GET 请求
GET 请求用于从服务器获取数据:
POST 请求
POST 请求用于向服务器新增数据:
DELETE 请求
DELETE 请求用于删除服务器上的数据:
PUT 请求
PUT 请求用于更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息):
PATCH 请求
PATCH 请求用于更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号):
请求方式小结
操作服务器上的数据除了要使用 URL地址,还需要指定______请求方式_______
操作服务器上的数据时:
获取服务器上的数据,需要使用 GET 方式
新增(添加)数据,需要使用 ____POST 方式
删除数据,需要使用 ____DELETE 方式
完整修改(更新)数据,需要使用 ____PUT 方式
修改(更新)部分数据,需要使用 ____PATCH 方式
Ajax 的基础用法
axios(发音:艾克C奥斯) 是前端圈最火的、专注于数据请求的库。
Axios
中文官网地址:www.axios-http.cn/
英文官网地址:www.npmjs.com/package/axi…
Axios 是一个基于 promise 网络请求库,作用于node.js
和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http
模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
特性
- 从浏览器创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF
axios 的基本语法如下:
GET 请求
测试 GET 请求的 URL 地址为 www.itcbc.com:3006/api/getbook…
示例
<!-- 1 引入axios -->
<script src="./lib/axios.js"></script>
<script>
/*
1 资源的地址 问后端要即可
2 我们负责用对 代码 确保 数据可以请求成功
3 不需要纠结 result的数据格式
只需要打印出result ,在里面 resut.data 找到数据
自己截图数据
4 把数据 存在自己的一个数组中
5 使用以前教过知识把数组渲染到页面中
*/
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks',
}).then((result) => {
console.log(result);
// result 请求成功的结果
// then 固定!! 是axios封装的一个代码 意思 服务器把数据返回了,then里面的代码就会被触发
// 底层套了两层data 也是后台程序员做的,不用纠结 别人怎么定义的 我只负责如何拿对
const arr = result.data.data; // 字段的名称 id、bookname、author。publisher 固定
render(arr);
});
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
GET 请求的查询参数
刚才查询回来的是所有图书的列表数据,如果想指定查询的条件,可以通过 params 选项来指定查询的参数:
如果要携带多个参数,只需要在 params 对象中指定多个查询参数项即可。示例代码如下:
指定参数查询演示
<!-- 1 引入axios -->
<script src="./lib/axios.js"></script>
<script>
/*
小结
1 在实际开发过程种,我们可以在前端 指定参数来查询对应的数据
2 指定参数的 参数的代码写法 必须要写在
params 对象中,以 键值对的形式存在
3 params 对象中,写什么样的键值对 规定要由后端来决定 前端不懂的时候问他
*/
axios({
// 请求方式
method: 'get',
// 请求地址
url: 'http://www.itcbc.com:3006/api/getbooks',
// 请求的参数
params: {
// 固定
// 键值对 是需要问后端程序员才知道
// bookname:"万少"// 后端就会返回 书名 为 万少的一堆数据
// author:"王勇"// 如果你这么写 后端什么都不返回(规则后端制定 )
// 在真实的开发场景中 往往会出现 前端以为我的代码参数都写对了 为什么没有结果
// 后端程序员都没有写到那个功能 !
// id:5913 // 根据id来查询数据 后端已经做好这个功能了
// bookname: '万少',
// author: '小马',
publisher: '6666',// 后端没有做这个功能
},
}).then((result) => {
console.log(result);
const arr = result.data.data; // 字段的名称 id、bookname、author。publisher 固定
render(arr);
});
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
另一种查询方式
<script src="./lib/axios.js"></script>
<script>
axios({
method: 'get',
// url: 'http://www.itcbc.com:3006/api/getbooks',
// params: { // 推荐直观
// id: 5913,
// bookname: 小黑,
// },
// url: 'http://www.itcbc.com:3006/api/getbooks?id=5913',
// url: 'http://www.itcbc.com:3006/api/getbooks?bookname=万少',
url: 'http://www.itcbc.com:3006/api/getbooks?bookname=小黑&id=5913',// ?属性名=属性值&属性名=属性值
}).then((result) => {
console.log(result);
const arr = result.data.data;
render(arr);
});
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
GET 案例:图书列表查询(用回车键)
<script>
// 1 打开页面 发送一个ajax 请求 获取数据 - 渲染页面
books()
// 2 获取输入框
const input = document.querySelector('input')
input.addEventListener('keydown', function (e) {
// 2.1 判断 按下的是不是回车键
if (e.key === 'Enter') {
const value = this.value.trim(); // trim() 去除 输入框的值 的两侧的 空字符串
// 2.3 判断是不是空字符串
if (value) {
// url 传参 ?属性名 = 属性值
const queryStr = `?bookname=${value}`;
books(queryStr); // 把参数带过去
}
// 空字符串
else {
books()
}
}
})
// 封装使用ajax来获取数据的函数
function books(query = '') {
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks' + query,
}).then((result) => {
console.log(result);
const arr = result.data.data; // 字段的名称 id、bookname、author。publisher 固定
render(arr);
});
}
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
POST 请求
使用 axios 发起 POST 请求时,只需要将 method 属性的值设置为 'POST' ,URL地址改为 '/api/addbook':
POST 案例:添加图书
思路:
点击 “添加” 按钮 获取输入框的值
使用 axios 发送Ajax请求,提交数据
如果添加成功,重新渲染页面中的数据
<button>添加</button>
<script src="../../JS/axios.js"></script>
<script>
const button = document.querySelector('button')
button.addEventListener('click', function(){
axios({
method: 'post',
url: 'http://www.itcbc.com:3006/api/addbook',
data: {
bookname:'人生长恨水长东',
author:'晚年不详',
publisher:'治愈书籍 强烈推荐'
}
}).then((result) => {
console.log(result);
});
})
</script>
delete请求
删除图书
示例
参照接口文档,发现删除图书,需要使用必填的id参数。
循环遍历数据时,将id值存储到 删除按钮的 自定义属性(data-id)中
单击 删除 按钮时,获取自定义属性data-id的值,这个值就是id
参照接口文档,配合axios的语法,发送请求,完成删除。
删除成功后,调用 books1(前面封装的获取图书函数),更新页面数据
confirm js中自带 确认框
如果用户点击 确定 返回true 点击 取消 - false
// 删除
const tbody = document.querySelector('tbody')
tbody.addEventListener('click',function(e){
if(e.target.className === 'del'){
// 删除确认框
// confirm js中自带 确认框
if(!confirm('是否确认删除')){
// 叹号取反 不删除则停止继续操作
return
}
const {id} = e.target.dataset
axios({
method: 'delete',
url: 'http://www.itcbc.com:3006/api/delbook',
params:{id}
}).then((result) => {
console.log(result);
books1()
});
}
})
appkey身份认证
服务器存储的图书,分为通用数据和个人数据。
默认获取、添加、删除、修改的都是通用数据。
在获取、添加、删除、修改时,如果带appkey参数,则表示使用个人数据。
修改图书
修改,最起码,得有修改的输入框。下面给出几种方案:
点击编辑,出现弹框
点击编辑,下拉一行,进行编辑
没有 编辑 按钮,点击单元格,创建input,进行修改
const tbody = document.querySelector('tbody');
// 全局变量
let arr;
// 书名
const booknameValue = document.querySelector('.bookname');
// 作者
const authorValue = document.querySelector('.author');
// 出版社
const publisherValue = document.querySelector('.publisher');
// 点击事件
tbody.addEventListener('click', function (event) {
// 判断找到的是不是这个类名
if (event.target.className === 'editbtn') {
// 获取a身上的下标
const { index } = event.target.dataset;
// 获取到 另外一个方法中的 数组
console.log(arr[index]);
// 把对应的数据显示到表单中
booknameValue.value=arr[index].bookname;
authorValue.value=arr[index].author;
publisherValue.value=arr[index].publisher;
}
});
btnadd.addEventListener('click', function () {
// 获取表单的值
const data = {
// 如何去获取
id: id,
bookname: booknameValue.value,
author: authorValue.value,
publisher: publisherValue.value,
appkey: 'lin123'
};
// 发送一个编辑 请求
axios({
url: 'http://www.itcbc.com:3006/api/updatebook',
method: 'put',
// query - params
// body - data
data,
}).then((result) => {
console.log(result);
getData();
});
// 提示编辑成功 ->调用 getData 实现重新获取最新的数据
});
如何获取指定form表单内的选择器
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
input[name] {
/* <input type="text" name="username" /> */
/* 表示选择到了 有name属性的input标签 */
background-color: red;
}
</style>
</head>
<body>
<form class="f1">
<input value="111" type="text" name="username" />
<input value="222" type="text" name="password" />
<input value="333" type="text" name="address" />
<input value="444" type="text" name="phone" />
<input type="text" />
<input type="text" />
<input type="text" />
<button type="button">注册数据</button>
</form>
<form class="f2" action="">
<input type="text" name="nickname" value="aabbcc" />
</form>
<script>
// 获取表单1 数据 对象格式
const obj1 = getForm('.f1');
// 获取表单2 数据 对象格式
const obj2 = getForm('.f2');
console.log(obj1);
console.log(obj2);
// query 只能传入 form标签的选择器
function getForm(query) { // 在定义函数的时候写形参 - 名字都可以随意改
const inputs = document.querySelectorAll(query + ' input[name]');
// const inputs = document.querySelectorAll('.f1 input[name]');
const obj = {};
inputs.forEach((dom) => {
obj[dom.name] = dom.value;
});
return obj;
}
</script>
服务器数据的变化
当添加图书后,页面的数据没有变化,怎么办?
我们必须弄清楚数据是怎么变化的。
接口相关的基础概念
1、接口的概念
使用 Ajax 请求数据时,被请求的 URL 地址,就叫做数据接口(简称:接口或 API 接口)。
同时,每个接口必须有对应的请求方式。例如:
www.itcbc.com:3006/api/getbook… 获取图书列表的接口(GET 请求) www.itcbc.com:3006/api/addbook 添加图书的接口(POST 请求)
2、接口文档的概念
接口文档就是接口的使用说明书,它是我们调用接口的依据。
接口文档的格式
组成部分 | 说明 |
---|---|
接口名称 | 接口的名称,用来快速区分每个接口的作用。如:登录接口、添加图书接口 |
接口 URL | 客户端发起 Ajax 调用此接口时,请求的 URL 地址 |
请求方式 | 接口的请求方式,如:GET、POST、PUT、DELETE 等 |
请求参数 | 请求此接口时,需要发送到服务器的查询参数或请求体 |
返回示例 | 当接口请求成功后,服务器响应回来的数据的基本格式 |
返回参数说明 | 接口响应结果的详细描述 |
network面板
开发或学习时,难免会遇到错误。遇到ajax方面的错误,该怎么排查呢?
答案是浏览器的 network 面板。
network,翻译为 “网络”
浏览器的开发者工具中,有一个面板为 network。(新版的chrome浏览器是中文版本的)
该工具可以抓取到所有的网络请求,当然包括ajax请求
我们可以使用该工具,查看当前Ajax请求的详细信息
查看请求方式
查看请求的URL地址
查看请求参数
查看响应结果
注意事项
有关Ajax方面的错误,不应只查看 “Console”面板,必须通过 “Network”面板进行排查
network面板介绍
network面板常用的设置
隐藏时间轴。初学阶段,用不到时间轴,可以将其隐藏,从而节省面板的空间
禁用浏览器缓存
模拟网络(网速)
No throttling -- 不限速
Fast 3G -- 模拟快速3G网络
Slow 3G – 模拟慢速3G网络
显示请求方式
network面板 查看 请求状态
非常重要
200 表示成功
pending 表示等待(可能网络不好或者断网了)
4xx 和 5xx 都表示不同程度的错误
Failed 表示失败
查看请求方式和完整URL
查看 传输到服务器的数据
查看 服务器响应结果
form 表单
了解
在网页中,表单主要负责数据采集功能。
表单的三个组成部分
网页中采集数据的表单由三个部分组成,分别是:表单标签、表单域、表单按钮。
1、表单标签 ------- HTML 的 < f or m > 就是表单标签,它是一个“容器”,用来将页面上指定的区域划定为表单区域:
2、表单域 ------- 表单域提供了采集用户信息的渠道,
常见的表单域有:input、textarea、select 等。
3、表单按钮 ------- 当表单数据填写完毕后,用户点击表单按钮,会触发表单的提交操作,从而把采集到的数据提交给服务器。
数据提交给服务器时,需要指定请求的方式与请求的 URL 地址
form 标签的属性一览表
form 标签最重要的 3 个属性分别是 action、method 和 enctype。简介信息如下表所示
注意:enctype 属性只能搭配 POST 提交方式一起使用;如果是 GET 提交,则 enctype 没有意义!
以 GET 方式提交表单数据
在 form 标签上,通过 action 属性指定提交的 URL 地址,通过 method 属性指定提交的方式为 GET
以 POST 方式提交表单数据
在 form 标签上,通过 action 属性指定提交的 URL 地址,通过 method 属性指定提交的方式为 POST,并通过 enctype 属性指定数据的编码方式为 application/x-www-form-urlencoded:
表单提交的问题
产生问题的原因:
表单身兼数职:既负责采集数据,又负责把数据提交到服务器!表单的默认提交行为会导致页面的跳转。
解决方案: form 表单只负责采集数据; Ajax 负责将数据提交到服务器。(符合:职能单一的原则)
旧方式
<!--
旧方式 提交数据 form标签的方式 提交
1 肯定会出现 刷新页面 调整页面的情况 (体验! 很糟糕)
2 输入框没name属性 没有把数据 提交给到后端
新的方式 ajax
1 异步 网络请求 (异步 同时执行多个事情 - 你一边正在使用网页功能而且数据提交 同时进行(整个网页 ))
2 规范 只要写到input标签想要数据提交 习惯的加上 name属性
如果使用ajax的技术来提交数据 是完全不给标签添加name属性
3 习惯下来 form input标签name 都一直在使用
-->
<form action="http://www.itcbc.com:3006/api/getbooks" method="get">
<div>
<label for="">用户名</label>
<input type="text" name="username">
</div>
<div>
<label for="">密码</label>
<input type="text" name="password">
</div>
<div>
<label for="">随便的测试</label>
<input type="text">
</div>
<!-- <button type="submit">提交</button> -->
<button >提交</button>
</form>
新的方式
<form>
<input type="text" name="username" />
<input type="text" name="password" />
<input type="text" name="gender" />
<button type="button">获取表单数据</button>
</form>
<script>
const button = document.querySelector('button')
button.addEventListener('click', function () {
const data1 = getForm('form')
console.log(data1);
return
// 把 form表单-里面所有的表单标签-name属性 转成 formdta对象
// const formObj = new FormData(document.querySelector('form'));
// formObj 对象 包含所有的表单数据(input name)
// console.log(formObj); // 直接打印 看不见里面的数据!!
// formObj 有forEach 方法 会遍历 它当中包含着 表单的数据
// formObj.forEach((值,键)=>{});
})
function getForm(query) {
// FormData js内置的对象 处理表单数据 需要被new 出来使用
// 1 快速 把 form表单中的带有name属性的数据 设置到 formdata 中
// const form = new FormData(document.querySelector('form'));
const form = new FormData(document.querySelector(query))
// 2 创建把数据 转成 get 参数格式 对象
// URL Search Params 用来处理 url上的参数 对象 也是可以被new
const usp = new URLSearchParams()
// 3 对form遍历
form.forEach((value, key) => {
usp.append(key, value)
})
// 4 usp 获取到了所有它等待转化的数据 开始进行转化
// 把添加到它身上的 数据 转成 url 的参数的格式
const data = usp.toString()
return data
}
/*
FormData 快速获取表单的数据
1 forEach
URLSearchParams 数据转成 get传参数据格式
1 append
2 toString()
*/
</script>
jQuery 的 serialize() 函数
jQuery 的 serialize() 函数能够一次性获取到表单中采集的数据,它的语法格式如下: $('表单元素的选择器').serialize();
serialize() 函数的使用注意点
在使用 serialize() 函数快速获取表单数据时,必须为每个表单域添加 name 属性! 例如下面的示例中,只能通过 serialize() 函数获取到密码的值:
serialize() 函数的其他特点
该方法是jQuery封装的,使用时必须引入jQuery 使用serialize(),各表单域必须有 name 属性 使用该方法得到的结果是一个查询字符串结构:name=value&name=value 该方法 能够 获取 隐藏域的值 该方法不能得到禁用状态的值 该方法不能得到文件域中的文件信息,所以不能完成文件上传
<form>
<input type="text" name="username" />
<input type="text" name="password" />
<input type="text" />
<button type="button">获取表单数据</button>
</form>
<script src="./jquery.js"></script>
<script>
// 序列化
// 把对象或者数组 转成 字符串格式 过程 序列化 JSON.stringify();
// 把字符串格式 转成 对象或者数组 反序列化 JSON.parse()
const button = document.querySelector('button');
// 假设我想要使用 快速获取表单数据 序列化 功能
// 1 直接用jq的 serialize
// 2 es6 新的对象 用这些新的对象 构造自己的序列化 方法 - 没有演示
// 3 传统- 自己写代码 获取每一个input标签的 自己写代码进行字符串拼接 没有演示
// 讲解js基础 对象 数组 字符串 转来转去
button.addEventListener('click', function () {
// 使用jq的方法 获取表单的数据 (字符串)
// username=11&password=22 get请求 两种传递参数的方式
// 1 params对象
// 2 在url上拼接字符串的形式 http:/api?username=11&password=22
// const data = $("form").serialize();
const data = myfunc('form'); // 不要这么做 人品坏
console.log(data);
});
function myfunc(query) {
return $(query).serialize();
}
</script>
FormData
FormData 是一个浏览器对象。用于管理表单数据。 IE10+支持。 可以这样理解,FormData的作用和 jQuery中的 serialize() 作用一样,用于快速收集表单数据 并且可以将创建的FormData对象直接提交给接口。
典型应用场景:FormData + Ajax 技术实现文件上传的功能。
FormData基本使用方法
假设需要收集 < form >……< /form > 里面的所有表单项的值 要求,每个表单元素都具有 name 属性
在提交数据前,可以使用下列API方法对数据进行查看和修改
FormData 和 serialize 的区别
共同点:
都需要设置表单各项的name属性。
都能快速收集表单数据
都能够获取到隐藏域(< input type="hidden" />)的值
都不能获取禁用状态(disabled)的值
不同点:
FormData属于原生的代码;serialiaze是jQuery封装的方法
FormData可以收集文件域(< input type="file"/>)的值,而serialize不能。如果有文件上传,则必须使用FormData。
得到的结果的数据类型不一样(知道即可)
结合 FormData 实现头像上传
主要的实现步骤:
使用文件选择器选择图片文件
把用户选择的文件存入 FormData 对象
使用 axios 把 FormData 发送给服务器
模拟文件选择器的点击事件
演示
<img src="" alt="">
<input type="file" accept="image/*">
<script>
/*
1 先允许用户选择本地的图片(很快 图片 上传视频)
1 指定文件上传的类型 只能是图片不能是其他 input标签一个属性 指定上传的文件的类型 accept
accept = "image/*"
accept = "image/*,video/*"
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input/file#唯一文件类型说明符
2 给input标签绑定 change事件 图片上传浏览器内存中 就会触发
3 this.files来获取文件数组
4 可选
1 直接把文件开始上传
1 先在网页显示一下用户选择的图片 - 来确定是不是一张
2 把图片上传到指定服务器
1 图片文件?axios
*/
const img = document.querySelector('img')
const input = document.querySelector('input')
input.addEventListener('change', function () {
console.log(this.files);
const file = this.files[0] // 要上传的文件对象
// 新的js对象 把浏览器内存中图片文件的地址 获取出来
const src = URL.createObjectURL(file)
console.log(src);
// 让图片显示出来
img.src = src
})
</script>
文件域补充
input标签的属性
文件域:< input type="file" />
accept 属性:控制能够选择的文件类型,比如 accept="image/png,image/jpeg"
multiple 属性:控制是否可以多选文件
文件对象
面向对象中,讲过,JS中表示一个人,需要用到对象。
JS中表示一个文件,也需要用对象,也就是文件对象
文件对象,是本地文件的一个表示。
通俗的说,在 JavaScript 中,使用 文件对象 表示一个本地文件。
文件对象不需要自己创建,可以通过文件域获取得到
选择一个或多个文件
根据文件域,找到它的 files 属性。files属性是一个伪数组,里面包含了一个或多个文件对象。
<img src="" alt="" />
<input type="file" accept="image/*" />
<script src="./lib/axios.js"></script>
<script>
/*
2 把图片上传到指定服务器
2 根据接口文档的要求来代码
url、请求类型、请求参数(重点)
url http://www.itcbc.com:3006/api/formdata
method post
请求参数 上传文件 给后端的参数 肯定是 formdata 类型
*/
const input = document.querySelector('input');
const img = document.querySelector('img');
input.addEventListener('change', function () {
const file = this.files[0];
const src = URL.createObjectURL(file);
img.src = src;
// 参数名称 avatar 参数值 file
const formdata = new FormData(); // 创建一个空formdata对象
formdata.append('avatar', file); // 接口要求 把文件追加到 formdata对象
// 把数据上传到服务器中 即可
axios({
method: 'post',
url: 'http://www.itcbc.com:3006/api/formdata',
data: formdata,
}).then((result) => {
console.log(result);
});
// 简写
// axios
// .post('http://www.itcbc.com:3006/api/formdata', formdata)
// .then((result) => {
// console.log(result);
// });
});
</script>
axios 请求方法的别名(简写)
在实际开发中,常用的 5 种请求方式分别是: GET、POST、PUT、PATCH、DELETE
为了简化开发者的使用过程,axios 为所有支持的请求方法提供了别名:
axios.get(url, config)
axios.delete(url, config)
axios.post(url, data, config)
axios.put(url, data, config)
axios.patch(url, data, config)
简化方法的参数
为了查看方法,下面将这些方法对齐:
axios.get() 的用法
使用 axios.get() 可以方便快捷地发起 GET 请求
axios.post() 的用法
使用 axios.post() 可以方便快捷地发起 POST 请求
演示
<script>
// axios.get() 直接发送get请求
// axios.post() 直接发送post请求
// axios.delete() 直接发送delete请求
// axios.put() 直接发送put请求
// console.dir(axios);
// get 请求
// axios.get(Url)
// axios.get(Url,{params:{参数}}) ;
axios.get('http://www.itcbc.com:3006/api/getbooks?appkey=lin123')
.then(result=>{
console.log(result);
})
// post请求
// axios.post(url,参数(对象));
// axios.post(url,参数(字符串格式));
// 第一种
// axios
// .post('http://www.itcbc.com:3006/api/addbook', {
// bookname: 'post请求1',
// author: 'post请求222',
// publisher: 'post请求33',
// appkey: 'lin123',
// }).then((result) => {
// console.log(result);
// });
// 第二种
// 创建变量
const url = 'http://www.itcbc.com:3006/api/addbook'
const query = 'bookname=111222&author=222222&publisher=33333&appkey=lin123';
axios.post(url, query).then((result)=>{
console.log(result);
})
// 第三种
// axios.post('http://www.itcbc.com:3006/api/addbook', 'bookname=111222&author=222222&publisher=33333&appkey=lin123').then((result)=>{
// console.log(result);
// })
</script>
拦截器
拦截器(interceptors)用来全局拦截 axios 的每一次请求与响应。
好处:可以把每个请求中,某些重复性的业务代码封装到拦截器中,提高代码的复用性。
需要在每个请求中分别展示和隐藏 loading 效果。示例代码如下:
拦截器案例
<img src="./20200527152202778.gif" alt="">
<button>发送请求</button>
<script src="../../JS/axios.js"></script>
<script>
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
document.querySelector('img').style.display = 'block';
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(
function (response) {
document.querySelector('img').style.display = 'none';
return response;
},
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
}
);
const button = document.querySelector('button');
button.addEventListener('click', function () {
// 发送网络请求
axios
.get('http://www.itcbc.co:3006/api/getbooks?appkey=wanshao1234')
.then((result) => {
console.log(result);
});
});
</script>
请求报文 & 响应报文
什么是请求报文和响应报文
客户端与服务器通信的过程是基于请求与响应的。其中:
请求报文规定了客户端以什么格式把数据发送给服务器
响应报文规定了服务器以什么格式把数据响应给客户端
请求报文 - 格式
请求报文由请求行(request line)、请求头部( header )、空行 和 请求体 4 个部分组成。图示如下:
注意:
在浏览器中,GET 请求比较特殊,它只有请求头,没有请求体。
在浏览器中,POST、PUT、PATCH、DELETE 请求既有请求头,又有请求体。
响应报文 - 格式
响应报文由状态行、响应头部、空行 和 响应体 4 个部分组成。图示如下:
URL参数
常用的5种请求方式,都可以在URL后面携带请求参数。
由于URL的长度有限制,所以请求参数一般都比较小,比如不能做文件上传
常用的请求参数有两种写法
/api/xxx?参数=值&参数=值 (这种格式的字符串叫做查询字符串,所以这样的参数叫做查询参数)
/api/xxx/值/值 (Restful 风格的接口用这种格式的参数)
请求体
除GET请求以外,其他4种常用的请求方式,都可以设置请求体。
请求体的大小没有限制,所以可以提交大量的数据
常用的请求体格式有如下三种:
参数=值&参数=值 (查询字符串格式)
'{ "id": 1, "name": "zs" }' (JSON格式)
new FormData() (FormData对象格式)
axios中,如何设置不同格式的请求体
第一种格式:参数=值&参数=值
第二种格式: '{ "id": 1, "name": "zs" }'
第三种格式: new FormData()
请求的时候,设置了不同格式的请求体,需要一个对应的请求头
使用axios就不用关心这个请求头了,因为axios已经帮我们处理好了加请求头这件事
不过写原生代码,就需要自己指定了
http 响应状态码
概念:http 响应状态码(Status Code)由三位数字组成,用来标识响应成功与否的状态。 作用:客户端浏览器根据响应状态码,即可判断出这次 http 请求是成功还是失败了。
常见的 http 响应状态码
http 响应状态码 Vs 业务状态码
正确区分响应状态码和业务状态码的不同,是保证使用 Ajax 不迷茫的必要前提。从如下 3 个方面进行区分: 所处的位置 表示的结果 通用性
- 所处的位置不同: 在响应头的状态行中所包含的状态码,或者请求列表中的Status,叫做“响应状态码”
在响应体的数据中所包含的状态码(案例中叫做code),叫做“业务状态码”
- 表示的结果不同: 响应状态码只能表示这次请求的成功与否(成功地失败了)
业务状态码用来表示这次业务处理的成功与否
- 通用性不同: 响应状态码是由 http 协议规定的,具有通用性。每个不同的状态码都有其标准的含义,不能乱用。
业务状态码是后端程序员自定义的,不具有通用性。