原生得AJAX
ajax的简介
AJAX 全称为Asynchronous JavaScript And XML ,就是异步的js 和XML
通过ajax 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
XML 简介
XML可以扩展标记语言
XML 被设计用来传输和存储数据
XML 和 HTML相似,不同的事HTM种中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据
比如说我有应该学生数据:
name = '孙悟空';age = 18;gender = "男";
用XML表示
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
现在已经被json取代了
用json表示:
{"name":"孙悟空","age":18,"gender":"男"}
AJAX的特点
优点
- 可以无需刷新页面与服务器端进行通信
- 允许你根据用户事件来更新部分页面内容
缺点
- 没有浏览历史,不能退回
- 存在跨域问题(同源)
- SEO不友好
AJAX的使用
核心对象
AJAX 设置请求参数
GET请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ajax GET 请求</title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
// 获取btutton元素
const btn = document.getElementsByTagName("button")[0];
const result = document.getElementById("result");
// 绑定事件
btn.onclick = function() {
//1、创建对象
const xhr = new XMLHttpRequest();
// 2、设置请求的方法
xhr.open("GET", "http://127.0.0.1:8000/server?a=100&b=200&c=300"); //a=100 b=200 c=300 为参数
// 3、发送
xhr.send();
// 4、事件绑定 服务端的返回的结果
// on 当 点击得时候
// readystate 是xhr 对象中的属性,表示状态 0 1 2 3 4
// change 改变
xhr.onreadystatechange = function() {
// 判断 (服务端都会所有的结果)
if (xhr.readyState === 4) {
// 判断响应码 200 404 403 401 500 以2开头的都表示成功
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 空行 体
// 1.响应行
// console.log(xhr.status); //状态码
// console.log(xhr.statusText); //状态字符串
// console.log(xhr.getAllResponseHeaders()); //所有响应头
// console.log(xhr.response); //响应体
// 设置result的文本
result.innerHTML = xhr.response;
} else {}
}
};
};
</script>
</body>
</html>
server.js
// 1、引入express
const { response } = require("express");
const express = require("express");
// 2、创建应用对象
const app = express();
// 3、创建路由规则
/**
* request 是对请求报文的封装
* respon 是对响应报文的封装
*/
app.get("/server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
// 设置响应
response.send("HELLO EXPRESS");
});
// all 可以接受任意请求
app.all("/server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
// 响应头 '*'表示所有的头信息 都可以接受
response.setHeader("Access-Control-Allow-Headers", "*");
// 设置响应
response.send("HELLO EXPRESS POST");
});
// 延时响应
app.all("/delay", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
response.setHeader("Access-Control-Allow-Headers", "*");
setTimeout(() => {
// 设置响应
response.send("延时响应");
}, 3000);
});
app.get("/ie", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
// 设置响应
response.send("HELLO IE");
});
// jQuery服务
app.all("/jQuery-server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
response.setHeader("Access-Control-Allow-Headers", "*");
const data = { name: "001" };
response.send(JSON.stringify(data));
});
// axios服务
app.all("/axios-server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
response.setHeader("Access-Control-Allow-Headers", "*");
const data = { name: "001" };
response.send(JSON.stringify(data));
});
app.all("/json-server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
// 响应头 '*'表示所有的头信息 都可以接受
response.setHeader("Access-Control-Allow-Headers", "*");
// 响应一个数据
const data = {
name: "atuigu",
};
// 对对象进行字符串转换
let str = JSON.stringify(data);
// 设置响应
response.send(str);
});
// jspnp服务
app.all("/jsonp-server", (request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
name: "ludan",
};
let str = JSON.stringify(data);
// 返回结果
response.end(`handle(${str})`);
});
// username
app.all("/jquery-jsonp-server", (request, response) => {
const data = {
name: "ludan",
city: ["汕头", "深圳", "广州"],
};
// 将数据返回转化为字符串
let str = JSON.stringify(data);
// 接受callbvack参数
let cb = request.query.callback;
// 返回结果
response.end(cb + `(` + str + `)`);
});
// 4、监听端口启动服务
app.listen(8000, () => {
console.log("服务器已经启动,8000 端口监听中....");
});
终端输如 node server.js
POST请求
参数在send方法中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ajax POST 请求</title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #999;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
// 获取元素对象
const result = document.getElementById("result");
// 绑定事件
result.addEventListener("mouseover", function() {
// 1、创建对象
const xhr = new XMLHttpRequest();
// 2、初始化 设置类型与URL
xhr.open("POST", "http://127.0.0.1:8000/server");
// 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>
server.js在上文中的get方法中有
AJAX设置请求头
将上述代码server.js 中的post 改成all
在绑定事件中添加
// 设置请求头
xhr.setRequestHeader(
"Content-Type",
"application/x-www-form-urlencoded"
); //固定写法
xhr.setRequestHeader("name", "atguigu");
服务端响应json数据
send方法只接受字符串或者数;所以要进行数据转化
<head>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #333;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.getElementById("result");
// 绑定键盘按下事件
window.onkeydown = function() {
// 发送请求
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType = "json";
// 初始化
xhr.open("GET", "http://127.0.0.1:8000/json-server");
// 发送
xhr.send();
// 事件绑定
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
//
// console.log(xhr.response);
// result.innerHTML = xhr.response;
// 手动对数据转化
/**let data = JSON.parse(xhr.response);
console.log(data);
result.innerHTML = data.name;
*/
console.log(xhr.response);
// 自动转换
result.innerHTML = xhr.response.name;
}
}
};
};
</script>
</body>
server.js的改变 添加以下代码
app.all("/json-server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
// 响应头 '*'表示所有的头信息 都可以接受
response.setHeader("Access-Control-Allow-Headers", "*");
// 响应一个数据
const data = {
name: "atuigu",
};
// 对对象进行字符串转换
let str = JSON.stringify(data);
// 设置响应
response.send(str);
});
nodemon自动重启工具
在终端输入
npm install -g nodemon
AJAX请求异常与网络超时
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px sienna;
}
</style>
</head>
<body>
<button>点击发送</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName("button")[0];
const result = document.getElementById("result");
btn.addEventListener("click", function() {
const xhr = new XMLHttpRequest();
// 超时设置
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function() {
alert("加载出错");
};
// 网络异常的回调
xhr.onerror = function() {
alert("你的网络似乎跑路了");
};
// 2、初始化 设置类型与URL
xhr.open("GET", "http://127.0.0.1:8000/delay");
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
};
});
</script>
</body>
</html>
AJAX取消请求
<button>点击发送</button>
<button>点击取消</button>
<script>
// 获取对象
const btn = document.querySelectorAll("button");
let x = null;
btn[0].onclick = function() {
x = new XMLHttpRequest();
x.open("GET", "http://127.0.0.1:8000/delay");
x.send();
};
// 取消
btn[1].onclick = function() {
x.abort();
};
</script>
Ajax重复发送请求
<button>发送请求</button>
<script>
// 获取对象
const btn = document.querySelectorAll("button");
let x = null;
// 标识变量
let isSending = false; //是否正发送AJAX请求
btn[0].onclick = function() {
// 判断标识变量
if (isSending) x.abort(); //如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
// 修改标识变量的值
isSending = true;
x.open("GET", "http://127.0.0.1:8000/delay");
x.send();
x.onreadystatechange = function() {
if (x.readyState === 4) {
// 修改标识变量
isSending = false;
}
};
};
</script>
jQuery中的AJAX
get请求
$.get(url,[data],[callback],[type])
url:请求的url地址
data:请求携带的参数
callback:载入成功时回调函数
type:设置返回内容格式,xml,html,script,json,text,_defalut
post请求
$.post(url,[data],[callback],[type])
url:请求的URL地址
data:请求携带的参数
callback:载入成功时的回调函数
jQuery发送Ajax请求
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link crossorigin="anonymous" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap-grid.min.css" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">jQuery发送Ajax请求</h2>
<button class="btn btn-primary">GET</button>
<button class="btn btn-danger">POST</button>
<button class="btn btn-info">通用型方法</button>
</div>
<script>
$("button")
.eq(0)
.click(function() {
$.get(
"http://127.0.0.1:8000/jQuery-server", {
a: 100,
b: 200,
c: 300,
},
function(data) {
console.log(data);
},
"json"
);
});
$("button")
.eq(1)
.click(function() {
$.post(
"http://127.0.0.1:8000/jQuery-server", {
a: 100,
b: 200,
c: 300,
},
function(data) {
console.log(data);
}
);
});
</script>
</body>
Axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script crossoring="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>
</head>
<body>
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
<script>
const btns = document.querySelectorAll("button");
// 配置baseURl
axios.defaults.baseURL = "http://127.0.0.1:8000";
btns[0].onclick = function() {
axios
.get("/axios-server", {
// url参数
params: {
id: 100,
vip: 7,
},
// 设置请求头信息
headers: {
name: "foobar",
},
})
.then((value) => {
console.log(value);
});
};
btns[1].onclick = function() {
axios
.post(
"/axios-server", {
username: "admin",
password: "admin",
}, {
// url参数
params: {
id: 200,
vip: 9,
},
// 设置请求头信息
headers: {
height: 180,
weight: 130,
},
// 请求体
}
)
.then((value) => {
console.log(value);
});
};
btns[2].onclick = function() {
axios({
// 请求方法
method: "POST",
// url
url: "/axios-server",
// utl 参数
params: {
vip: 10,
level: 30,
},
// 头信息
headers: {
a: 100,
b: 200,
},
// 请求体参数
data: {
username: "admin",
password: "admin",
},
}).then((response) => {
console.log(response);
// 响应状态码
console.log(response.status);
// 响应状态字符串
console.log(response.statusText);
// 响应头信息
console.log(response.headers);
// 响应体
console.log(response.data);
});
};
</script>
</body>
</html>
server.js添加
// axios服务
app.all("/axios-server", (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", " *");
response.setHeader("Access-Control-Allow-Headers", "*");
const data = { name: "001" };
response.send(JSON.stringify(data));
});
fetch函数发送ajax请求
<button>发送</button>
<script>
const btn = document.querySelector("button");
btn.onclick = function() {
fetch("http://127.0.0.1:8000/axios-server?vip=10", {
// 请求方法
method: "POST",
// 请求头
headers: {
name: "ludan",
},
//请求体
body: "usernam=admin&&password=admin",
})
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
});
};
</script>
server.js添加以下代码
HTTP
HTTP协议请求报文与响应文本结构
http(hypertext transport protocol) 协议【超文本传输协议】,协议详细规定了浏览器和万维网服务器直接按互相通信的规则。
约定,规则
请求报文
重点是格式与参数
行 POST …/ s?ie=utf-8 HTTP/1.1
头 Content-type: text/html;charset=utf-8 格式要掌握 ,名字+冒号+空格+值
Content-length:2048
Content-enoding:gzip
空行 空行必须有
体
<head>
<body>
<h1>
卤蛋
</h1>
</body>
</head>
(若为post是必需的,get不是必需的)
响应报文
行 HTTP/1.1 200 OK
头 Host: atguigu.com 格式要掌握 ,名字+冒号+空格+值
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrom 83
空行
体 username=admin&passwordadmin (若为post是必需的,get不是必需的)
*404
*403
*403
*500
*200
Express框架的介绍与基本使用
Express基于Nodes.js平台,快速、开放、极简的Web开发框架
// 1、引入express
const express = require("express");
// 2、创建应用对象
const app = express();
// 3、创建路由规则
/**
* request 是对请求报文的封装
* respon 是对响应报文的封装
*/
app.get("/", (request, response) => {
// 设置响应
response.send("HELLO EXPRESS");
});
// 4、监听端口启动服务
app.listen(8000, () => {
console.log("服务器已经启动,8000 端口监听中....");
});
终端操作
浏览器
跨域
出现跨域的原因
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
当前页面url 被请求页面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 否 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)
非同源限制
【1】无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
【2】无法接触非同源网页的 DOM
【3】无法向非同源地址发送 AJAX 请求
同源策略
同源:协议、域名、端口号 必须完全相同
违背同源策略就是跨域
注意要在127.0.0.1:9000/home端口打开
<button>点击获取数据</button>
<script>
const btn = document.querySelector("button");
btn.onclick = function() {
const x = new XMLHttpRequest();
// 这里时满足同源策略的 所以url可以简写
x.open("GET", "/data");
x.send();
x.onreadystatechange = function() {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
console.log(x.response);
}
}
};
};
</script>
在文件中新建server.js
const app = express();
app.get("/home", (request, response) => {
// 响应一个页面
response.sendFile(__dirname + "/index.html");
});
app.get("/data", (request, response) => {
// 响应一个页面
response.send("用户数据");
});
app.listen(9000, () => {
console.log("服务已经启动");
});
解决跨域
JSONP
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个
返回的结果要其他语法能识别
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #666;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
// 处理数据
function handle(data) {
// 获取元素
const result = document.getElementById("result");
result.innerHTML = data.name;
}
</script>
<!-- <script src="http://127.0.0.1:5500/%E4%BB%A3%E7%A0%81/%E8%B7%A8%E5%9F%9F/JSONP/js/app.js"></script> -->
<script src="http:127.0.0.1:8000/jsonp-server"></script>
</body>
</html>
在最初的server.js中添加
// jspnp服务
app.all("/jsonp-server", (request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
name: "ludan",
};
let str = JSON.stringify(data);
// 返回结果
response.end(`handle(${str})`);
});
cors
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
【前端设置】根据xhr.withCredentials字段判断是否带有cookie
原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
**② jQuery ajax **
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
③vue-resource
Vue.http.options.credentials = true
④ axios
axios.defaults.withCredentials = true