一 Ajax相关知识
Ajax(Asynchronous JavaScript and XML,异步的 JavaScriopt 和 XML)是一种用于创建动态 Web 应用程序的技术,它使用 JavaScript 和 XML(或 JSON)等技术来实现异步数据传输和动态更新页面内容。
通过 Ajax 技术,可以在不刷新整个页面的情况下,向服务器发送请求,获取数据并进行处理,从而实现更加流畅、响应更快的 Web 应用程序。Ajax 技术最初是由 Google 推广的,现在已经成为了 Web 开发中不可或缺的一部分。
Ajax 的核心是 XMLHttpRequest 对象,它提供了在客户端浏览器和服务器之间发送 HTTP 请求和接收响应的功能。使用 XMLHttpRequest 对象,可以在不刷新整个页面的情况下更新部分页面内容,从而实现异步数据传输。除此之外,还可以使用 jQuery 等 JavaScript 库中提供的 Ajax 方法、Fetch API 等技术来实现 Ajax 功能。
(一) http请求响应相关
客户端和服务器
-
客户端是向服务器发请求的。
- 浏览器的地址栏,只能发送get请求
- postman软件,可以各种请求,类似postman这样的软件有很多
- a标签 img标签 link标签 script标签 form标签....
- ajax(异步局部刷新,提升用户体验)
- App
- 小程序
- ....
-
服务器主要接收客户端的请求,给出响应。通过node的框架叫express,提供服务器功能。
url
- 互联网上的资源都有一个url,通过url就可以定位到互联网上的某个资源。
- 协议名称 + 主机名称 + 端口号 + 路径 + 文件 + 查询所需的字符串 + HASH
- http:// baidu.com 8 /css/reset.css ?a=1&b=2&c=3 #abc
http:
- HyperText Transfer Protocol 超文本传输协议。本质就是客户端和服务器之间沟通交流的规则。
- http请求(Request):由客户端(浏览器)向服务器发出请求
- http响应(Response):由服务器给出响应
http请求(请求报文):
-
请求行
- 请求方法 get post put ....
- url 不管是什么样的请求方式,都可以通过url传递参数
- http协议版本
-
请求头
- Content-Type: text/plain, application/x-www-form-urlencoded, application/json, mutipul/form-data
-
请求体(请求正文),就是传给服务器的数据,post请求和put请求才有请求体,get请求没有请求体
http响应(响应报文):
- 响应行
- 响应头
- 响应体(响应正文)
(二) 总结ajax
创建xhr对象,使用构造函数 XMLHttpRequest 就可以创建一个 XHR 对象。
csharp
let xhr = new XMLHttpRequest();
ajax对象中的属性如下:
属性名 | 含义 |
---|---|
readyState | 返回一个数字,表示请求的状态: 0 -- UNSET -- XHR对象已创建或已被 abort() 方法重置。 1 -- OPENDED -- open() 方法已经被调用。 2 -- HEADERS_RECEIVED -- send() 方法已经被调用,并且响应头和响应状态已经可获得。 3 -- LOADING -- 下载中, responseText 属性已经包含部分数据。 4 -- DONE -- 所有响应数据接收完毕。 |
status | 响应状态码,如 404、200 等。 |
statusText | 响应状态码的文本描述/响应状态码,如 200 对应的是 "OK"。 |
responseXML | 接收格式为 XML 的响应数据,返回一个 document 对象。 |
responseText | 获取响应文本,返回一个字符串。 |
responseType | 用于设置响应内容的类型 xhr2 |
response | 返回的类型取决于 responseType 的设置。 xhr2 |
timeout | 设置超时时间。xhr2 |
ajax对象中的方法如下:
方法名 | 含义 |
---|---|
open() | 初始化 HTTP 请求,用来指定请求方式和 URL。 xhr.open(method, url, [async], [user], [password]) |
send() | 发送 HTTP 请求,参数可以设置请求体,没有请求体无需设置参数。 |
setRequestHeader() | 设置 HTTP 请求头的值。必须在 open() 之后、send() 之前调用。 |
abort() | 如果请求已被发出,则立刻中止请求。 |
getAllResponseHeaders() | 以字符串形式返回所有的响应头。 |
getResponseHeader() | 返回指定的响应头。 |
ajax对象中的事件如下:
事件名 | 含义 |
---|---|
readystatechange | readyState 属性值发生变化触发该事件。 |
abort | 请求终止时触发。 |
error | 请求遇到错误时触发。 |
loadstart | 接收到响应数据时触发。 |
loadend | 当请求结束(包括请求成功和请求失败)时触发,且在error、abort、load之后触发 |
load | 请求成功完成时触发。 |
loaded | 当请求结束时触发, 无论请求成功 ( load) 还是失败 (abor 或 error)。 |
progress | 当请求接收到更多数据时,周期性地触发。 |
timeout | 在预设时间内没有接收到响应时触发。 |
异步请求:
- 在发请求之后,其它的同步任务都已经执行完毕了。
同步请求:
- 在发请求之后,需要等到响应完全结束后才会执行剩下同步任务。
默认情况下,ajax发的请求,都是异步的,通过open方法中的第3个参数可以设置同步
- true 表示异步请求 , 不写也是true
- false 表示同步请求,基本上不用
(三) 同源策略及解决跨域问题方案
1.同源策略
同源策略是浏览器的一种安全策略,要求ajax代码所在的页面url中的协议,域名,端口与ajax请求中url中的协议,域名,端口要完全一样。举例:有一个这样的域名:www.wangcai.com
- zhidao.wangcai.com 不同源
- www.wangcai.com:8080 不同源
- www.wangcai.com 不同源
- www.wangcai.com/phone/index... 同源
- www.wangcai.com/phone/huawe... 同源
同源策略判定:
- 源:协议 + 域名 + 端口
- 同源:相同的协议 && 相同域名 && 相同的端口
- 不同源:不同的协议 || 不同的域名 || 不同的端口
不受同源策略的限制情况:
- 资源的引入 如:img标签的src link标签的href script标签的src
- 页面中的超连接 a标签中的href
- 表单的提交
- 重定向页面
2.解决跨域的方案
要抵抗同源策略,叫跨域,常见解决跨域的方案:
- cors
- jsonp
- 前端配置代理
cors解决跨域(后端去配置解决)
perl
// 导入模块const path = require('path');const express = require('express');// 创建 express 实例const app = express();
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "../client", "index.html"))})
app.get('/getData', (req, res) => {
console.log("来到服务器了~~")// 通过请求头,抵抗同源策略// res.set('Access-Control-Allow-Origin', 'http://localhost:3000');// res.set('Access-Control-Allow-Origin', 'http://192.168.217.1:3000');// 请允许多个域名来请求// const allowOrigins = ['http://localhost:3000','http://192.168.217.1:3000']// if (allowOrigins.includes(req.get('Origin'))) {// res.set('Access-Control-Allow-Origin', req.get('Origin'));// }// 允许所有的域名
res. set ( 'Access-Control-Allow-Origin' , '*' );
res.send('hello malu')});
app.listen(3000, () => {
console.log('服务器启动了,端口是3000');})
配置好之后,即使不同源,也可以获取数据,如下:
还有一个模块,叫cors模块,使用如下:www.npmjs.com/package/cor...
JSONP(前端去做,不受同源策略的限制)
JSONP不是ajax,JSONP发请求本质是利用script标签的src发的请求
- 前端代码:
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button id="btn">点我发请求</button>
<div id="box"></div>
<script>
let btn = document.querySelector("#btn");
// jsonp的原理
function jsonp(options) {
let callName = "fn";
// data就是服务器响应的数据
window[callName] = function (data) {
console.log("fn函数执行了....");
if (data != null) {
options.success(data)
} else {
options.fail();
}
}
// 利用script标签的src发请求,没有跨域问题
// "fn(JSON.stringify({a:1,b:2}))"
// http://127.0.0.1:3000/?callBack=fn
let url = options.url + "?callBack=" + callName
let scriptEle = document.createElement("script");
scriptEle.src = url;
document.body.append(scriptEle)
}
btn.onclick = function () {
jsonp({
url: "http://127.0.0.1:3000/",
success: function (data) {
console.log("data:", data);
},
fail: function (err) {
console.log("数据请求失败了");
}
})
}
</script>
</body>
</html>
- 后端代码:
javascript
const path = require('path');
const express = require('express');
const app = express();
// http://127.0.0.1:3000/?callBack=fn
app.get("/", (req, res) => {
let cb = req.query.callBack;
// "fn(JSON.stringify({a:1,b:2}))"
res.send(`${cb}(JSON.stringify({a:1,b:2}))`)
})
app.listen(3000, () => {
console.log('服务器启动了,端口是3000');
})
(四) 开源接口
如果请求的url,得到的是一个json数据,通常这个url叫API接口。
如下:
arduino
https://docs.tenapi.cn/
https://www.free-api.com/
https://api.aa1.cn/
二 原生Ajax经典四步
(一) 原生Ajax经典四步
-
第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
csharplet xhr = new XMLHttpRequest()
-
第二步:监听对象状态的变化
- 监听XMLHttpRequest对象状态的变化
inixhr.onreadystatechange = function () { if (xhr.readyState == 4) { console.log(xhr.response); } }
- 或者监听onload事件(请求完成时触发)
ini// 等价于下面这么写 xhr.onload = () => { console.log(xhr.response); }
-
第三步:配置网络请求(通过open方法)
kotlinxhr.open("get", "http://127.0.0.1:3001/getData")
-
第四步:发送send网络请求
- send()参数写的是请求体 只有post请求方式才有请求体
- 就是给后端传递数据
scssxhr.send()
(二) 原生Ajax请求前后端代码示例
1.package.json用到的依赖
perl
{
"name": "code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"dependencies": {
"@koa/router": "^12.0.0",
"axios": "^0.27.2",
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"express-session": "^1.17.2",
"koa": "^2.13.4",
"koa-body": "^5.0.0",
"koa-bodyparser": "^4.4.0",
"koa-logger": "^3.2.1",
"koa-static": "^5.0.0",
"koa2-cors": "^2.0.6",
"moment": "^2.30.1",
"mongodb": "^4.4.0",
"nprogress": "^0.2.0",
"qs": "^6.10.2"
},
"author": "",
"license": "ISC"
}
2.前端代码:发送Ajax请求
xml
<script>
// 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
let xhr = new XMLHttpRequest()
// 第二步:监听XMLHttpRequest对象状态的变化,或者监听onload事件(请求完成时触发)
// 方式一 onreadystatechange
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
console.log(xhr.response);
}
}
// 方式二 onload
// xhr.onload = () => {
// console.log(xhr.response);
// }
// 第三步:配置网络请求(通过open方法)
xhr.open("get", "http://127.0.0.1:3001/getData")
// 第四步:发送send网络请求
xhr.send()
</script>
3.后端代码:监听到后接收请求并响应
ini
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router"); //路由
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router(); //路由
app.use(cors());
app.use(logger());
app.use(koaBody());
// 写了一个接口 请求方式是get 请求的api是/getData
// 请求返回的状态码是200 返回的结果是helloajax
router.get("/getData", async (ctx, next) => {
ctx.status = 200
ctx.body = "helloajax"
})
app.use(router.routes())
//允许任意方式发送的请求
router.allowedMethods()
//监听端口
app.listen(3001,()=>{
console.log("服务器跑起来了");
})
三 处理后端响应的数据
(一) 后端相应json数据
- 前端设置:xhr.responseType = 'json' 将得到的json串转成对象
- 后端设置:ctx.type = "json"
1.前端代码:发送ajax请求
xml
<script>
// 1)创建对象
let xhr = new XMLHttpRequest()
// 2)绑定load事件
xhr.onload = function () {
// 在network面板中 找到响应头,看到响应的数据类型是:
// Content-Type:application/json; charset=utf-8
console . log (xhr. response ); //从{"name":"哈哈"}变成{name:"哈哈"}
}
// 可以通过xhr.responseType这种方式,将得到的json串转成对象
xhr. responseType = 'json'
// 3)配置网络请求
xhr.open('get', 'http://127.0.0.1:3001/json')
// 4)发送请求
xhr.send()
</script>
2.后端代码:监听到后接收请求并响应json格式数据
ini
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();
app.use(cors());
app.use(logger());
app.use(koaBody());
router.get("/json", async (ctx) => {
ctx.status = 200
ctx. type = "json"
ctx. body = {
name : "哈哈"
//无论是json格式还是对象格式都会被浏览器自动转为json格式传输,所以都可
//"name": "哈哈"
}
})
app.use(router.routes())
router.allowedMethods()
app.listen(3001, () => {
//启动服务器并监听特定端口的方法
console.log("服务器跑起来了");
})
(二) 后端响应xml的数据
- 前端设置:xhr.responseType = 'json' 将得到的json串转成对象
- 后端设置:ctx.type = "xml"
1.前端代码:发送ajax请求
xml
<script>
let xhr = new XMLHttpRequest()
xhr.onload = () => {
//用xhr.responseXML获取返回数据,不用xhr.response
console.log(xhr. responseXML);
}
xhr.open("get", "http://127.0.0.1:3001/xml")
xhr.send()
</script>
2.后端代码:监听到后接收请求并响应xml格式数据
ini
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();
app.use(cors());
app.use(logger());
app.use(koaBody());
router.get("/xml", async (ctx) => {
ctx.status = 200
ctx. type = "xml"
ctx. body = `
<content>
<name>哈哈</name>
</content>`
})
app.use(router.routes())
router.allowedMethods()
app.listen(3001, () => {
console.log("服务器跑起来了");
})
四 前端发送请求传递参数/数据
(一) get传参(通过url传参)
1.方式一: query
前端传参:xhr.open('get', 'http://127.0.0.1:3002/getData ? name **=**zhangsan & address=zz')
后端获取:router.get("/getData", (ctx) => {}
ctx.query
2.方式二: params
看network面板:通过params传参 并没有payload选项
前端传参:xhr.open("get", "http://127.0.0.1:3002/getData /zhangsan/18")
后端获取:router.get("/getData /:name/:age", (ctx) => {}
ctx.params
3.代码示例
- 前端代码
xml
<script>
let xhr = new XMLHttpRequest()
xhr.onload = () => {
console.log(xhr.response);
}
xhr.responseType = "json"
// ----------------------------------------------------
// get传参的第一种方式: 通过query传参
xhr.open('get', 'http://127.0.0.1:3002/getData?name=zhangsan&address=zz')
// 重点: 看network面板
// 请求地址b:Request URL:http://127.0.0.1:3000/get?name=zhangsan&age=18&address=zz
// 在network里面,有一个payload,表示传递给服务器的参数
// payload -- Query String Parameters 查询字符串
// view source: 查看参数的源码
// view parsed: 解析参数 name=zhangsan&age=18&address=zz
// 注意:前端给后端传递的数据非常重要 如果你调用接口失败了,你要考虑是否是你的参数传递问题
// ----------------------------------------------------
// get传参的第二种方式: 通过params传参
// 看network面板:通过params传参 并没有payload选项
// xhr.open("get", "http://127.0.0.1:3002/getData/zhangsan/18")
xhr.send()
</script>
- 后端代码
ini
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();
app.use(cors());
app.use(logger());
app.use(koaBody());
// get -- query传参
router.get("/getData", (ctx) => {
ctx.status = 200
// 前端请求服务器传递的参数 后端又响应给我们
ctx. body = ctx. query
console.log(ctx.query.name);
})
// get -- params传参 动态路由
// router.get(" /getData/:name/:age", (ctx) => {
// ctx.status = 200
// // 前端请求服务器传递的参数 后端又响应给我们
// ctx.body = ctx.params
// })
app.use(router.routes())
router.allowedMethods();
app.listen(3002, () => {
console.log("running in http://127.0.0.1:3002");
})
(二) post传参(通过send(请求体))
默认情况下,看network面板中,请求头request Header里面 有一个
Content-Type:text/plain;charset=UTF-8 -- 表示给服务器默认传递的是纯文本的参数类型
再看payload,里面显示的是 Request Payload
name=zhangsan&age=18&address=zz
但是在开发中,需要传递json格式
1)x-www-form-urlencode
2)json
3)formdata
还有mutipul/form-data
0.post传参的几种格式
get请求只能通过url把数据扔给服务器,post,put请求可以不仅可以通过url把数据扔给服务器,也可以通过请求体把数据扔给服务器。把数据通过请求体扔给服务器,也是有多个格式的:
-
text/plain
- 默认的请求体类型,如果不设置请求头字段 Content-type,默认就是该种类型
- 求体只要是字符串就可以,后端不会做任何处理
-
application/x-www-form-urlencoded
- 需要设置请求头 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
- 要求请求体是查询字符串,如 a=100&b=200
- 点击提交按钮提交表单(非Ajax),如果 Method 是 Post,默认请求体内容就是 x-www-form-urlencoded
-
application/json
- 设置设置请求头 xhr.setRequestHeader('Content-type', 'application/json');
- 要求请求体是 json 格式的字符串
-
multipart/form-data
1.传递"name=zhangsan&age=18"类型数据(setRequestHeader)
前端传参:
xhr.open("post", "http://127.0.0.1:3002/postData")
设置请求头:xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
请求头一定要在 open() 之后,send() 之前设置
xhr.send("name=zhangsan&age=18&address=zz")
后端获取:ctx.request.body
代码示例:
- 前端代码
xml
<script>
let xhr = new XMLHttpRequest()
xhr.onload = () => {
console.log(xhr.response);
}
xhr.responseType = "json"
xhr.open("post", "http://127.0.0.1:3002/postData")
xhr. setRequestHeader ( 'Content-Type' , 'application/x-www-form-urlencoded' )
// post传参 需要把参数放在请求体中
// send('请求体')
xhr. send ( "name=zhangsan&age=18&address=zz" )
</script>
- 后端代码
ini
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();
app.use(cors());
app.use(logger());
app.use(koaBody());
router.post("/postData", (ctx) => {
ctx.status = 200
// 接受post传递过来的数据
ctx. body = ctx. request . body
console.log(ctx.request.body.name);
})
app.use(router.routes())
router.allowedMethods()
app.listen(3002, () => {
console.log("running in http://127.0.0.1:3002");
})
2.传递json数据(setRequestHeader)
前端传参:
xhr.open("post", "http://127.0.0.1:3002/postData")
设置请求头:xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify({ name: "zhangsan", age: 18 }))
后端获取:ctx.request.body
代码示例:
- 前端代码
xml
<script>
let xhr = new XMLHttpRequest()
xhr.onload = () => {
console.log(xhr.response);
}
xhr.responseType="json"
xhr.open("post", "http://127.0.0.1:3001/postData")
// 设置请求头
// application / json 表示以json形式传递
xhr. setRequestHeader ( 'Content-Type' , 'application/json' )
xhr. send ( JSON . stringify ({ name : "zhangsan" , age : 18 }))
</script>
- 后端代码:同上
2.传递formData数据(FormData)
请求体(send()的方法的参数)除了是字符串,也可以是 formData 对象。如果请求体是 FormData 对象,浏览器会自动设置请求头字段 Content-type 为 multipart/form-data。
FormData不仅可以传递普通数据,还可以上传文件。
a. 传递普通数据
前端传参:
xhr.open("post", "http://127.0.0.1:3002/postData")
let formData = new FormData(formEle) 容器 -- formEle元素的数据
xhr.send(formData)
PS:payload的view source跟其他不同
后端获取:ctx.request.body
代码示例:
- 前端代码
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- form表单有默认的提交事件 -->
<!-- onsubmit="return false" 阻止默认事件的 -->
<form onsubmit="return false" class="info">
<input type="text" name="username">
<input type="text" name="pwd">
</form>
<button class="send">发送请求</button>
</head>
<body>
<script>
let formEle = document.querySelector(".info")
let btnEle = document.querySelector(".send")
btnEle.onclick = function () {
let xhr = new XMLHttpRequest()
xhr.responseType = "json"
xhr.onload = () => {
console.log(xhr.response);
}
xhr.open("post", "http://127.0.0.1:3001/postData")
// 容器 -- formEle元素的数据
// 创建formData容器时,传递一个formDOM元素
// 自动将form元素中的表单控制添加到formData中
let formData = new FormData (formEle)
// send中不只可以放字符串,还可以放formdata对象
xhr. send (formData)
}
</script>
</body>
</html>
- 后端代码:同上
b. 上传文件
(三) 非ajax用form表单发送请求传递参数/上传数据
五 基于Ajax封装的Axios请求方法(常用)
(一) Axios 介绍
Axios 是前端最流行的 ajax 请求库 ,没有之一,react、vue官方都推荐使用 的 Ajax 请求库。
- 官方网站:axios-http.com
- 仓库地址:github.com/axios/axios
- 中文文档:axios-http.com/zh/docs/int...
PS:与ajax、fetch相比,请求体不需用JSON.stringify()方法从对象转为json字符串
1.Axios特点
- 基于 XMLHttpRequest + Promise 的异步的 Ajax 请求库
- 浏览器端、Node端都可以使用
- 支持请求和响应拦截器
- 支持请求取消
- 批量发送多个请求
- 支持请求与响应的数据转换(二次封装)
2.Axios引入方式
xml
<script src="axios脚本文件地址"</script>//下载后在页面引入
xml
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"</script>//CDN
(二) Axios的基本使用
1. async await等方式使用Axios(简单--但是需注意使用限制)
由于
async/await
是ECMAScript 2017中的一部分,而且在IE和一些旧的浏览器中不支持,所以使用时务必要小心。
- axios(config): 通用/最本质的发送意类型请求的方式。
- axios(url, config): 第一个参数是地址,第二个参数是配置项。
- axios.request(config): 等同于axios(config) (了解)
- axios.get(url, config): 发get请求 (查)
- axios.delete(url, config): 发delete请求 (删)
- axios.post(url, data, config): 发post请求 (增)
- axios.put(url, data, config): 发put请求 (改)
- axios.patch(url[, data[, config]]) 发送patch请求
javascript
// 简单但有限制方式-async await方式 axios.get()
async function getUser() { try { const response = await axios. get ( '/user?ID=12345' ); console.log(response); } catch (error) { console.error(error); } }
// 稍麻烦但无限制方式-promise.then()方式 axios.get().then()
axios. get ( '/user?ID=12345' )
. then(function (response) {
// 处理成功情况
console.log(response);
})
. catch(function (error) {
// 处理错误情况
console.log(error);
})
. finally(function () {
// 总是会执行
});
// 上述请求也可以按以下方式完成(可选)
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// 总是会执行
});
2. 更多方式使用Axios(麻烦)
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入axio-->
< script src = "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js" ></ script >
</head>
<body>
<button id="btn">使用axios发请求</button>
<script>
const btn = document.querySelector("#btn");
btn.onclick = async function(){
// 使用方式零 async await 方式(简单但有限制)
const res = await axios. get ( "https://tenapi.cn/v2/toutiaohot" )
// const res = await axios.get("/toutiaohot",{
// baseURL:"https://tenapi.cn/v2",
// timemout:5000
// })
console.log(res);
// 使用方式零点五 axios.get() axios.post() (稍复杂但无限制)
// axios.get("/toutiaohot",{
// baseURL:"https://tenapi.cn/v2",
// timemout:5000
// }).then(res => {
// console.log(res);
// }).catch(reason => {
// console.log('请求失败!', reason);
// });
// 使用方式一 axios函数使用一个对象作为参数
// axios({
// method:"GET",
// url:'https://tenapi.cn/v2/toutiaohot'
// }).then(res => {
// console.log(res);
// }).catch(reason => {
// console.log('请求失败!', reason);
// });
// 使用方式二 第一个参数是url,第二个参数是请求配置对象
// axios("/toutiaohot",{
// method:"GET",
// baseURL:"https://tenapi.cn/v2",
// timemout:5000
// }).then(res => {
// console.log(res);
// }).catch(reason => {
// console.log('请求失败!', reason);
// });
// 使用方式三 axios.request() 方法同 axios 本身
// axios.request("/toutiaohot",{
// method:"GET",
// baseURL:"https://tenapi.cn/v2",
// timemout:5000
// }).then(res => {
// console.log(res);
// }).catch(reason => {
// console.log('请求失败!', reason);
// });
}
</script>
</body>
</html>
(三) Axios请求配置项
1.常用的请求配置项
url、method、baseURL、headers、data、timeout、responseType
注意:
上面那些配置项全部适用于axios(config)方法
但使用 axios.post( url , data, config)等 方法时
- 作为请求体data不写在配置项config里,而在外面
- url也是
perl
{
// `url` 是用于请求的服务器 URL
url: '/user',
// `method` 是创建请求时使用的方法
method: 'get', // default
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
// `headers` 是即将被发送的请求头
headers: {
'Content-type': 'appliation/json'
},
// `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
},
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout: 1000,
// `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default
}
- 每次发送请求时设置配置项
scss
axios({
配置项...});
axios(url, {
配置项...});
axios.get(url, {
配置项...});
axios.post(url, data, {
配置项...});
- 设置全局配置项,将被应用到每一个请求。
ini
axios.defaults.baseURL = "http://api.example.com";
axios.defaults.timeout = 2000;
axios.defaults.headers = {token:"abc",a:1,b:2}
2.代码示例
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<button id="btn1">get</button>
<button id="btn2">post</button>
<button id="btn3">put</button>
<button id="btn4">delete</button>
<script>
const btn1 = document.querySelector("#btn1");
const btn2 = document.querySelector("#btn2");
const btn3 = document.querySelector("#btn3");
const btn4 = document.querySelector("#btn4");
// 做全局配置
axios.defaults.baseURL = "http://localhost:3000"
axios.defaults.timeout = 5000;
axios.defaults.headers.token = "xxxx"; // 不用管
// get
btn1.onclick = function () {
// axios.get("/users?a=1&b=2").then(res => {
axios.get("/users", {
params: { name: "malu" } // 也是配置问号传参
}).then(res => {
console.log(res.data);
}).catch(reason => {
console.log('请求失败:', reason);
})
}
// post
btn2.onclick = function () {
// Content-Type: application/json
let user = {
id: 3,
name: "xq"
};
// axios.post中第二个参数是请求体, 第三个参数是配置对象
// 传递的参数的类型是:Content-Type: application/json
// 不需要通过JSON.stringify包了
axios.post("/users", user, {}).then(res => {
console.log(res.data);
}).catch(reason => {
console.log('请求失败:', reason);
})
}
// put
btn3.onclick = function () {
let user = {
name: "malu666"
};
axios.put("/users/1", user, {}).then(res => {
console.log(res.data);
}).catch(reason => {
console.log('请求失败:', reason);
})
}
// delete
btn4.onclick = function () {
axios.delete("/users/3").then(res => {
console.log(res.data);
}).catch(reason => {
console.log('请求失败:', reason);
})
}
</script>
</body>
</html>
六 浏览器自带的Fetch请求方法(不常用)
Fetch API 被设计用来取代 XMLHttpRequest,它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。
Fetch API 的主要特点包括:
- Promise 风格的 API:Fetch API 提供了 Promise 风格的 API,可以更加方便地处理异步请求和响应。
- 更加灵活的请求和响应:Fetch API 可以发送任何类型的请求,包括 GET、POST、PUT、DELETE 等,也可以接收任何类型的响应,包括文本、JSON、二进制数据等。
- 更加强大的响应处理:Fetch API 提供了一系列的响应处理方法,包括 json()、text()、blob()、arrayBuffer() 等,可以更加方便地处理响应数据。
(一) 主要步骤
- 发送fetch请求
const res = await fetch( "httpbin.org/get?a=1" )
- 把返回的ReadableStream可读流处理成json数据
const data = await res.json() ;
另:fetch()、res.json()都返回promise对象
get,post,put,delete请求区别:
get默认,而其他发送其他方式请求需要设置配置项如请求方式method、请求体body
javascript
const res = await fetch("http://httpbin.org/put", {
method : "put" , // 修改数据
headers : {
'Content-type' : 'application/json' ,
},
body : JSON . stringify (user)
} )
(二) 代码示例
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<!-- fetch为浏览器自带方法,所以不需要引入组件啥的 -->
<!-- CRUD 增删改查 -->
<button id="btn1">get请求</button>
<button id="btn2">post请求</button>
<button id="btn3">put请求</button>
<button id="btn4">delete请求</button>
<script>
let btn1 = document.querySelector("#btn1");
let btn2 = document.querySelector("#btn2");
let btn3 = document.querySelector("#btn3");
let btn4 = document.querySelector("#btn4");
// get请求--(默认method: "get")
btn1.onclick = async function () {
// fetch()、res.json()都返回promise对象
const res = await fetch ( "http://httpbin.org/get?a=1" )
// 把返回的ReadableStream可读流处理成json数据
const data = await res. json ();
console.log(data);
}
// post请求
btn2.onclick = async function () {
let user = { name: "malu", age: 10, sex: "man", score: { chinese: 110, maths: 90, english: 88 } }
const res = await fetch("http://httpbin.org/post", {
method : "post" ,
headers : {
'Content-type' : 'application/json' ,
},
body : JSON . stringify (user)
})
const data = await res.json()
console.log("data:", data)
}
// put请求
btn3.onclick = async function () {
let user = { id: 1, name: "malu", age: 10, sex: "woman", score: { chinese: 66, maths: 44, english: 99 } }
const res = await fetch ( "http://httpbin.org/put" , {
method : "put" , // 修改数据
headers : {
'Content-type' : 'application/json' ,
},
body : JSON . stringify (user)
})
const data = await res.json()
console.log("data:", data)
}
// delete请求(这个是假的接口跑不通,只做写法演示)
btn4.onclick = async function () {
const res = await fetch ( "http://httpbin.org/delete/1" , {
method : "delete" ,
headers : {
'Content-type' : 'application/json' ,
}
})
const data = await res. json ()
console.log("data:", data)
}
</script>
</body>
</html>
七 案例:检测用户是否存在
(一) 原生Ajax方法解决
1.前端代码
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>用户注册</h1>
<form>
<ul>
<li>用户名:<input type="text" name="username" id="user">
<span id="msg"></span>
</li>
<li>密码:<input type="text" name="pws"></li>
<li>确认密码:<input type="text" name="pws"></li>
<li><input type="submit" value="注册"></li>
</ul>
</form>
<script>
// 获取元素
let unameEle = document.getElementById("user")
let msg = document.getElementById("msg")
// 绑定失焦事件
unameEle.onblur = function () {
// 获得用户名值
//let uname = unameEle.value.trim()
let uname = this.value.trim();
//console.log(uname);
// 发送请求
// 声明ajax对象
let xhr = new XMLHttpRequest()
// 监听onload状态
xhr.onload = () => {
// 如果返回true--用户名可用
msg.textContent = xhr.response.msg
msg.style.color = xhr.response.msgColor
}
// 后台Boolean类型传到前端变字符串类型,需设置xhr.responseType = "json"
// 从json串转为对象
xhr.responseType = "json"
// post版本
// 配置请求,传递参数
xhr.open("post", `http://127.0.0.1:3001/check`)
// 设置请求头,请求参数为x-www-form的格式
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 发送请求
xhr.send(`uname=${uname}`)
// get版本
// 配置请求,传递参数
// xhr.open("get", `http://127.0.0.1:3001/check?uname=${uname}`)
// 发送请求
// xhr.send()
}
</script>
</body>
</html>
2.后端代码
javascript
const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();
app.use(cors());
app.use(logger());
app.use(koaBody());
// 模拟从数据库中取到的用户信息
let userData = ["wc", "xq", "admin"];
// post版本
router.post("/check", (ctx) => {
ctx.status = 200
ctx.type = 'json'
// 如果在users中找到相同的则返回该用户名已经被注册
console.log(ctx.request.body.uname);
if (userData.includes(ctx.request.body.uname)) {
ctx.body = {
code: 0,
msg: "用户名已被占用",
msgColor: "red"
}
// 反之
} else {
ctx.body = {
code: 1,
msg: "用户名可用",
msgColor: "green"
}
}
})
// get版本
// 需求:如果在users中找到相同的则返回该用户名已经被注册,反之
// router.get("/check", (ctx) => {
// ctx.type = 'json'
// // console.log(ctx.query.name.trim());
// // 如果在users中找到相同的则返回该用户名已经被注册
// if (userData.includes(ctx.query.name.trim())) {
// ctx.body = {
// code: 0,
// msg: "用户名已被占用",
// msgColor: "red"
// }
// // 反之
// } else {
// ctx.body = {
// code: 1,
// msg: "用户名可用",
// msgColor: "green"
// }
// }
// })
app.use(router.routes())
router.allowedMethods()
app.listen(3001, () => {
console.log("服务器启动");
})
(二) Axios方法解决
仅修改部分前端代码(后端代码不变)
xml
<script>
// 获取元素
let unameEle = document.getElementById("user")
let msg = document.getElementById("msg")
// 绑定失焦事件
unameEle.onblur = async function () {
// 获得用户名值
let unameValue = this.value.trim();
// 用Axios发送请求
let uname = { uname : unameValue }
const res = await axios. post (
"http://127.0.0.1:3001/check" ,
uname,
{
headers : {
'Content-type' : 'application/json'
},
// 默认
// responseType: 'json'
}
);
// 修改样式
// 只有Axios返回值套了一层data
msg.textContent = res. data . msg
msg.style.color = res. data . msgColor
}
</script>
(三) Fetch方法解决
仅修改部分前端代码(后端代码不变)
xml
...
<script>
// 获取元素
let unameEle = document.getElementById("user")
let msg = document.getElementById("msg")
// 绑定失焦事件
unameEle.onblur = async function () {
// 获得用户名值
let unameValue = this.value.trim();
// 用Fetch发送请求
let uname = { uname : unameValue }
const res = await fetch ( "http://127.0.0.1:3001/check" , {
method : "post" ,
headers : {
'Content-type' : 'application/json'
},
body : JSON . stringify (uname)
})
const data = await res. json ()
// 修改样式
msg.textContent = data. msg
msg.style.color = data. msgColor
}
</script>