AJAX
简介
什么是 AJAX?
AJAX = Asynchronous JavaScript And XML.
AJAX 并非编程语言。
AJAX 仅仅组合了:
浏览器内建的 XMLHttpRequest 对象(从 web 服务器请求数据)
JavaScript 和 HTML DOM(显示或使用数据)
Ajax 是一个令人误导的名称。Ajax 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。
Ajax 允许通过与场景后面的 Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分,而不需要重新加载整个页面。
AJAX特点
ajax优点
1)可以无需刷新页面而与服务器端进行通信。
2)可以根据用户事件更新部分页面内容
ajax缺点
1)不利于SEO
2)存在跨域问题(同源)
3)没有浏览历史,不能回退
工作原理
事件触发:如点击按钮或页面加载
AJAX请求:通过 JavaScript 创建一个 XMLHttpRequest 对象,向服务器发送请求。
服务器处理请求:服务器(通常使用 PHP、Node.js 等)接收请求,处理并返回响应数据(JSON、XML、HTML等)。
AJAX响应处理:浏览器接收响应,使用 JavaScript 在页面上更新内容,而无需重新加载整个页面。
XMLHttpRequest 对象:
XMLHttpRequest 对象是 AJAX 的基石。
创建 XMLHttpRequest 对象
定义回调函数
打开 XMLHttpRequest 对象
向服务器发送请求
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
创建
语法:
变量 = new XMLHttpRequest()
方法
new XMLHttpRequest():创建新的 XMLHttpRequest 对象。
abort(): 取消当前请求。
getAllResponseHeaders():返回头部信息。
getResponseHeader():返回特定的头部信息。
open(method, url, async, user, psw):
规定请求:
method:请求类型 GET 或 POST
url:文件位置
async:true(异步)或 false(同步)
user:可选的用户名
psw:可选的密码
send():发送请求。
对象属性
onreadystatechange:定义当 readyState 属性发生变化时调用的函数。
readyState:保存 XMLHttpRequest 的状态。值为:
0:请求未初始化
1:服务器连接已建立
2:请求已收到
3:正在处理请求
4:请求已完成且响应已就绪
responseText:以字符串形式返回响应数据。
responseXML:以 XML 数据返回响应数据。
status:返回请求的状态码。
200: "OK"
403: "Forbidden"
404: "Not Found"
statusText:返回状态文本(比如 "OK" 或 "Not Found")
onreadystatechange属性
xhr.onreadystatechange = function(){
//判断 (服务端返回了所有的结果)
if(xhr.readyState === 4){
//判断响应的状态码
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回的结果 行 头 空行 体
//响应行
// console.log(xhr.status)//响应状态码
// console.log(xhr.statusText);//状态字符串
// console.log(xhr.getAllResponseHeaders);//所有响应头
// console.log(xhr.response);////响应体
//设置result的文本
result.innerHTML = xhr.response;
}
}
GET 还是 POST?
GET 比 POST 更简单更快,可用于大多数情况下。
不过,请在以下情况始终使用 POST:
缓存文件不是选项(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 无大小限制)
发送用户输入(可包含未知字符),POST 比 GET 更强大更安全
GET
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const button = document.querySelector('button');
const result = document.querySelector('#result');
//绑定点击事件
button.addEventListener('click', function(){
//创建对象
const xhr = new XMLHttpRequest();
//初始化,设置请求方式和请求地址 方法open()
xhr.open('GET', 'http://127.0.0.1:4000/server?a=100&b=200&c=300');
//发送
xhr.send();
//事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
//判断 (服务端返回了所有的结果)
if(xhr.readyState === 4){
//判断响应的状态码
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回的结果 行 头 空行 体
//响应行
// console.log(xhr.status)//响应状态码
// console.log(xhr.statusText);//状态字符串
// console.log(xhr.getAllResponseHeaders);//所有响应头
// console.log(xhr.response);////响应体
//设置result的文本
result.innerHTML = xhr.response;
}
}
}
})
POST
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax Post请求</title>
<style>
#result{
width: 200px;
height: 100px;
border:1px solid #903;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
//获取元素对象
const result = document.getElementById('result');
//绑定事件
result.addEventListener('mouseenter', function(){
//1、创建对象
const xhr = new XMLHttpRequest();
//2、设置请求方式和请求地址
xhr.open('POST', 'http://127.0.0.1:3000/server');
//设置请求头 Content-Type设置请求体内容的类型 application/x-www-form-urlencoded参数查询字符串的固定类型
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
//3、发送
xhr.send('a:100&b:200&c:300')
//4、事件绑定
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回的结果
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
JSON对象
简介
JavaScript 对象表示法 (JSON) 是一种基于文本的标准格式,用于表示基于 JavaScript 对象语法的结构化数据。它通常用于在 Web 应用中传输数据(例如,将一些数据从服务器发送到客户端,以便可以在网页上显示,反之亦然)。
JSON 以字符串形式存在 - 当你想要通过网络传输数据时很有用。当你想要访问数据时,需要将其转换为原生 JavaScript 对象。
反序列化:将字符串 转换为 原生对象
序列化:将原生对象 转换为 字符串 以便可以通过网络传输
JSON 字符串可以存储在自己的文件中,该文件基本上只是一个扩展名为 .json、MIME type 为 application/json 的文本文件。
JSON结构
JSON 是一个字符串,其格式非常类似于 JavaScript 对象文字格式。可以在 JSON 中包含与标准 JavaScript 对象中相同的基本数据类型 - 字符串、数字、数组、布尔值和其他对象文字。这允许构建数据层次结构,如下所示:
{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
要进一步访问层次结构中的数据,必须将所需的属性名称和数组索引链接在一起。例如,要访问成员列表中列出的第二个英雄的第三个超级大国:
superHeroes["members"][1]["powers"][2];
首先,我们有变量名 - superHeroes。
在其中,我们想要访问 members 属性,因此我们使用 ["members"]。
members 包含一个由对象填充的数组。我们想要访问数组内的第二个对象,因此我们使用 [1]。
在这个对象内部,我们想要访问 powers 属性,所以我们使用 ["powers"]。
powers 属性内部是一个包含所选英雄超能力的数组。我们想要第三个,所以我们使用 [2]。
JSON格式
数据采用名称/值对
数据以逗号分隔
对象封装在左括号和右大括号内
空对象可以用{}
数组封装在左方括号和右方括号中
空数组可以用[]
成员由双引号中包含的键值对表示
每个成员在对象结构中都应该有一个唯一的键
如果成员是字符串,则成员的值必须包含在双引号中
布尔值使用小写的 or 文字表示truefalse
数字值使用双精度浮点格式表示,并且不应包含前导零
字符串中的“冒犯性”字符需要使用反斜杠字符进行转义\
Null 值由小写的文本表示null
日期和类似的对象类型没有得到充分支持,应该转换为字符串
对象或数组值的每个成员都必须后跟一个逗号,最后一个成员除外
JSON 文件的标准扩展名为'.json'
JSON 文件的 MIME 类型为'application/json'
//1.定义基本格式
const person = {"name": "张三", age: 23, 'gender': true};
const ps = [{"name": "张三", "age": 23, "gender": true},
{"name": "李四", "age": 24, "gender": true},
JSON和JS对象互转
JSON字符串转换为JS对象,使用JSON.parse()
方法
const obj = JSON.parse('{"a":"Hello","b":"World"}')//结果是:{a:'Hello',b:'World'}
JS 对象转换为JSON字符串,使用JSON.stringify()方法
const json = JSON.stringify('{a:'Hello',b:'World'}')//结果是:{"a":"Hello","b":"World"}
注意
JSON 纯粹是一个具有指定数据格式的字符串 - 它只包含属性,不包含方法。
JSON 要求在字符串和属性名称周围使用双引号。除了包围整个 JSON 字符串之外,单引号无效。
JSON 实际上可以采用任何可有效包含在 JSON 中的数据类型的形式,而不仅仅是数组或对象。例如,单个字符串或数字就是有效的 JSON。
与 JavaScript 代码中对象属性可以不加引号不同,在 JSON 中,只能将带引号的字符串用作属性。
IE 缓存问题
IE浏览器会缓存网页中的GET和XHR的内容,并且在IE浏览器中如果请求方式是get方式的话,IE浏览器会进行识别,如果该get请求的URL是第一次请求的话,会请求项目的后台,从数据库中获取数据,如果该get请求的URL不是第一次请求的话,那么该URL就不会请求项目后台,IE浏览器会直接从缓存中拿到上次该URL获取的数据,无论是什么插件的get方式请求,IE浏览器都会这样进行处理的。
IE浏览器会对相同请求的AJAX,进行缓存,当你删除数据后,在调用同样的接口,IE不会刷新,只会把第一次请求该接口的数据拿出来,所以,你看到的页面永远都是第一次请求的AJAX返回的数据
解决方法
方法一:提交方式是get方式,但是在传递的参数中添加一个随机数或当前时间戳的参数,从而保证每次URL请求唯一性,从而解决在IE浏览器中从数据库中获取数据:
//向服务器获取新的结果通过获取时间戳,防止IE浏览器走缓存
xhr.open('GET','http://127.0.0.1:3000/ie?t='+Date.now())
2. 方法二:提交方式修改为post方法,这样就不会出现这样的问题了。
超时与网络异常
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请求超时与网络异常</title>
<style>
#result{
width: 200px;
height: 100px;
border:1px solid #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
const btn = document.querySelector('button')
const result = document.getElementById('result')
btn.addEventListener('click',function(){
const xhr = new XMLHttpRequest()
//超时设置 2s
xhr.timeout = 2000
//超时回调
xhr.ontimeout = function(){
alert("网络异常,请稍后重试")
}
//网络异常回调
xhr.ontimeout = function(){
alert("你的网络似乎出了一些问题")
}
xhr.open('GET','http://127.0.0.1:3000/delay')
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState === 4)
{
if(xhr.status >= 200 && xhr.status <300){
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
重复请求问题
当用户频繁并重复请求相同的功能时,如果不处理,服务器会依次响应用户的每一次请求,这样容易导致响应时间过长,用户体验不好。因此可以在每件事件触发请求时,标识一个变量判断该请求是否正在发送,如果正在发送,就取消该请求,创新一个新的请求,保证不会有重复的请求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重复请求问题</title>
</head>
<body>
<button>点击发送</button>
<script>
//获取元素对象
const btns = document.querySelectorAll('button')
let x = null;
//标识变量
let isSending = false;//是否正在发送AJAX请求
btns[0].onclick = function(){
//判断标识变量
//如果正在发送,则取消该请求,创建一个新的请求,保证不会有重复的请求
if(isSending) x.abort()
x = new XMLHttpRequest()
//修改标识变量的值
isSending = true;
x.open("GET",'http://127.0.0.1:4000/delay')
x.send()
x.onreadystatechange = function(){
if(x.readyState === 4){
//修改标识变量
isSending = false
}
}
}
//abort
btns[1].onclick = function(){
x.abort()
}
</script>
</body>
</html>
AXIOS
简介
Axios是一个基于promise 的 HTTP 库(类似于jQuery的Ajax,用于HTTP请求),可以用在浏览器和 node.js中(既可以用于客户端也可以用于node.js编写的服务端)。
axios(ajax i/o system)不是一种新技术,本质上也是对原生XHR(XMLHttpReques)的封装,只不过它是基于Promise的,是Promise的实现版本,符合最新的ES规范。
特性
从浏览器创建 XMLHttpRequests请求
从node.js创建http请求
支持 Promise API
拦截请求和响应,比如:在请求前添加授权和响应前做一些事情。
转换请求数据和响应数据,比如:进行请求加密或者响应数据加密。
取消请求
自动转换JSON数据
客户端支持防御XSRF
Axios的基础用法(get、post、put 等请求方法)
get:一般用于获取数据
post:一般用于提交数据(表单提交与文件上传)
patch:更新数据(只将修改的数据推送到后端(服务端))
put:更新数据(所有数据推送到服务端)
delete:删除数据
GET方法
方式一:请求别名的使用 axios.get(url,[,config])用于获取数据
1、如果不带有参数,如下:
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
axios
.get("/data.json")
.then((result) => {
// result不是直接的返回结果
console.log("数据:",result);
// result.data才是真正的返回结果
console.log("真正的数据:",result.data);
})
.catch((err) => {
console.log(err);
});
},
};
</script>
2、如果带有参数,如下:
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
// 第一种方式:将参数直接写在url中
// 向给定ID的用户发起请求
axios
.get("/data.json?id=5")
.then((result) => {
// 处理成功情况
console.log(result);
})
.catch((err) => {
// 处理错误情况
console.log(err);
});
// 第二种方式:将参数直接写在params中
axios
.get("/data.json", {
//带参数时 ————若无参数时直接省略params对象不写
params: {
id: 5,
},
})
.then((result) => {
// result不是直接的返回结果
console.log("数据:", result);
// result.data才是真正的返回结果
console.log("真正的数据:", result.data);
})
.catch((err) => {
console.log(err);
});
// 支持async/await用法
// axios 是一个基于 promise 网络请求库, 这意味着, 你必须使用 ES6 的 then() 或者 ES8 的 async/await 来处理 Promise 实例对象。
// 注意: 由于async/await 是ECMAScript 2017中的一部分,而且在IE和一些旧的浏览器中不支持,所以使用时务必要小心。
async function getUser() {
try {
const response = await axios.get("/user?ID=12345");
console.log(response);
} catch (error) {
console.error(error);
}
}
},
};
</script>
方式二:通过向axios传递相关配置来创建请求
1、r如果不带参数,如下:
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
axios({
method: "get",
url: "/data.json"
}).then((res) => {
// result不是直接的返回结果
console.log("数据:", result);
// result.data才是真正的返回结果
console.log("真正的数据:", result.data);
});
},
};
</script>
2、如果带有参数,如下:
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
axios({
method: "get",
url: "/data.json",
//带参数时 ————若无参数时直接省略params对象不写
params: {
id: 5,
},
}).then((result) => {
// result不是直接的返回结果
console.log("数据:", result);
// result.data才是真正的返回结果
console.log("真正的数据:", result.data);
});
},
};
</script>
POST方法
post请求常用的数据请求格式有三种:
1、Content-Type : application/x-www-form-urlencoded。
ajax默认的数据格式。请求体中的数据会以json字符串的形式发送到后端。
2、Content-Type : application/json ; charset=utf-8。
axios默认的数据格式。请求体中的数据会以普通表单形式(键值对)发送到后端。
3、Content-Type : multipart/form-data 。
它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。
方式一:请求别名的使用 axios.post(url, [ , data [ , config]])用于发送数据 ’data’对象是作为请求主体被发送的数据
1、axios发送post无参请求,如下:
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//把get无参请求的get改为post即可
axios.post("/data.json").then(res=>{
console.log(res)
});
},
};
</script>
2、axios发送post有参请求,两种传参形式,如下:
i. 查询字符串形式
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//发送post请求携带参数,直接使用"uname=dingding&upwd=123456"
axios.post("/data.json", "uname=dingding&upwd=123456").then(res=>{
console.log(res)
});
},
};
</script>
ii.对象形式
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//发送post请求携带参数,这种传参方式后台得使用requestBody处理
axios.post("/data.json", {uname:"dingding",upwd:123456}).then(res=>{
console.log(res)
});
},
};
</script>
方式二:通过向axios传递相关配置来创建请求
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
let data = {uname:"dingding",upwd:123456};
axios({
method:'post',
url:'/data.json',
// 与get请求使用params不同的是,post请求使用data属性
data:data
}).then(res=>{
console.log(res)
})
},
};
</script>
Express框架
简介
Express 是一个流行的 Node.js 框架,为开发者提供了简洁的 API,用于处理 HTTP 请求、响应,以及管理中间件、路由和错误处理。Express 简化了构建 RESTful API、Web 应用程序和微服务的过程。
创建基本 Express 应用
创建一个 app.js 文件:
const express = require('express');
const app = express();
// 定义路由
app.get('/', (req, res) => {
res.send('Hello, World!');
});
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
运行 app.js 文件后,将拥有一个在端口 3000 上运行的 Web 服务器。
Express 的主要功能
路由(Routing)
路由是指定义应用程序端点(URI)及如何响应客户端请求的方法。在 Express 中,路由使用方法如 app.get(), app.post(), app.put(), 和 app.delete() 等,分别对应 HTTP 的请求方法。
路由的使用示例代码:
const express = require('express');
const app = express();
// GET 请求的路由
app.get('/', (req, res) => {
res.send('Hello World!');
});
// POST 请求的路由
app.post('/login', (req, res) => {
// 处理登录逻辑
});
app.listen(3000, () => {
console.log('App listening on port 3000');
});
上述例子中当用户发送 GET 请求至根路径 '/' 时,服务器会响应 'Hello World!'。类似地,当用户发送 POST 请求至 '/login' 路径时,服务器会处理登录逻辑。
获取请求报文参数:
在 Express 中,可以通过 req.params、req.query 和 req.body 来获取请求参数:
// 路由参数
app.get('/user/:id', (req, res) => {
const userId = req.params.id; // 获取路由参数
});
// 查询参数
app.get('/search', (req, res) => {
const query = req.query.q; // 获取查询参数
});
// 请求体参数
app.post('/login', (req, res) => {
const username = req.body.username; // 获取 POST 请求体参数
});
在上述例子中,req.params.id 用于获取路由参数,req.query.q 用于获取查询参数,req.body.username 用于获取 POST 请求体参数。