看完我的笔记不懂也会懂----Ajax
- Ajax(Asynchronous JavaScript And XML)
- 本次学习所用到的插件
- XML
- JSON
- 关于AJAX
- HTTP协议
- AJAX重点之XMLHttpRequest对象
- 服务端 实例
- ajax-get 实例
- ajax-post 实例
- 设置请求头信息
- 服务端响应JSON数据
- AJAX关于在IE中的缓存问题
- 超时设置、回调与网络异常的回调
- 取消ajax请求
- jquery发送ajax请求
- fetch函数发送ajax请求
- 跨域
Ajax(Asynchronous JavaScript And XML)
通过ajax浏览器可以像服务器发送异步请求,最大的优势:可以在不刷新网页的情况下,异步的向后台发送请求,在前端接受并展示数据
本次学习所用到的插件
- Node.js
- NPM
- express(简单的web服务器)
- nodemon(用于自动重启node服务器)
XML
-
XML是什么? 有什么用?
- XML 被设计用来传输和存储数据
- XML 的设计宗旨是传输数据(XML),而非显示数据(HTML)
- XML 被设计为具有自我描述性
- XML 标签没有被预定义。您需要自行定义标签
-
语法:
<?xml version="1.0" encoding="utf-8"> <root> <!-- 标签可以自由命名 --> <name>Fitz</name> <!-- 必须正确关闭标签 --> </root>
<root> <!-- 属性必须加引号 --> <!-- 尽量不要使用属性 --> <name gender="male">Fitz</name> <address province="GD">HouJie</address> </root>
<root> <!-- 这是错误的属性使用方法 --> <attr attr1="error" attr2="wrong">属性不应该这样用</attr> </root>
<root> <!-- 特殊的符号应该使用实体 --> <sample>使用实体例如:大于号 ></sample> </root>
JSON
由于JSON 比 XML 更小、更快,更易解析。所以现在AJAX返回的数据格式多是使用JSON
{
"name": "Fitz",
"hobby": "computer science",
"dream": "good at math"
}
关于AJAX
- ajax的优点
- 无需刷新页面即可与服务器进行通讯
- 允许根据用户事件来更新部分页面内容
- ajax的缺点
- 没有浏览历史,这就导致不能回退
- 存在跨域问题
- 对SEO不友好
HTTP协议
HTTP(hypertext transport protocol)超文本传输协议,规定了浏览器和万维网服务器之间互相通信的规则
-
请求报文
- 重要格式与参数
行 ====> GET/POST /s?ie=utf-8 HTTP/1.1 头 ====> Host: baidu.com Cookie: name=trash content-type: application/x-www-form-urlencoded user-Agent: chrome 83 空行 ====> 体 ====> username=root&password=root
-
响应报文
-
重要格式与参数
行 ====> HTTP/1.1 200 OK 头 ====> Host: baidu.com content-type: text/html;charset=utf-8 content-length: 2048 空行 ====> 体 ====> <html> <head></head> <body></body> </html>
AJAX重点之XMLHttpRequest对象
XMLHttpRequest对象作用是前端向服务端发送ajax请求,别接收来自服务端的数据
``` javascript {.line-numbers}
//主要步骤
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server');
// 3 发送请求
xhr.send();
// 4 事件绑定 处理服务端返回的结果
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}`);
}else{
console.log('Some Error !');
}
}
```
关于 onreadystatechange与readyState
每当 readyState 改变时,就会触发 onreadystatechange 事件,readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
服务端 实例
使用插件 express
//引入express
const express = require("express");
//创建应用对象
const app = express();
//创建路由规则
app.get('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装
//设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息');
})
app.post('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装
//设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息 -post method');
})
app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})
ajax-get 实例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title>
<style>
* {
margin: 0;
padding: 0;
}
#result{
width: 200px;
height: 100px;
border: solid 1px black;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server?name=fitz');
// 3 发送请求
xhr.send();
// 4 事件绑定 处理服务端返回的结果
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}`);
//展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>
ajax-post 实例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title>
<style>
* {
margin: 0;
padding: 0;
}
#result{
width: 200px;
height: 100px;
border: solid 1px black;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
// 3 发送请求
xhr.send('name=Fitz&gender=Male'); //post请求参数应在send方法中添加
// 4 事件绑定 处理服务端返回的结果
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}`);
//展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>
设置请求头信息
// 2 初始化 设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 3 发送请求
xhr.send('name=Fitz&gender=Male');
服务端响应JSON数据
方法一
前端代码
var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法一
//通过手动转换来响应JSON
let data = JSON.parse(xhr.response);
console.log(data);
div.innerHTML = data.username;
}
}
}
}
方法二
前端代码
var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法二
//自动转换
console.log(xhr.response);
div.innerHTML = xhr.response.username;
}
}
}
}
后端代码
//引入express
const express = require("express");
const { json } = require("body-parser");
//创建应用对象
const app = express();
// //创建路由规则
app.all('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装
//设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.setHeader('Access-Control-Allow-Header','*')
//要发送回去前端的数据
const data = {
username: 'root',
password: 'root123'
}
const data2str = JSON.stringify(data); //手动将data对象转换为JSON字符串
response.send(data2str); //send方法只能接收一个字符串
})
app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})
AJAX关于在IE中的缓存问题
解决方法:使用时间戳以保证每次的URL都不一样(参数不一样)
var xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/ie?t'+Date.now()); //使用时间戳
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}
超时设置、回调与网络异常的回调
var xhr = new XMLHttpRequest();
//设置超时
xhr.timeout = 2000;
//设置超时回调
xhr.ontimeout = function(){
console.log('你的网络似乎有些慢');
}
//设置断网回调
xhr.onerror = function(){
console.log('你的网络似乎有些问题');
}
xhr.open("GET",'http://127.0.0.1:8000/cancel); //使用时间戳
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}
取消ajax请求
var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var div = document.getElementById('result');
var xhr = null;
addEventListener('click',function(){
if(xhr){
xhr.abort();
}
xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/cancel');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}
})
btn2.onclick = function(){
xhr.abort();
}
jquery发送ajax请求
$(function(){
//get
$('button').eq(0).click(function(){
$.get('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
},'json')
})
//post
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
})
})
//通用方法
$('button').eq(2).click(function(){
$.ajax({
//url
url: 'http://127.0.0.1:8000/jquery',
//要发送的参数
data: {
a: 'a',
b: 'b'
},
//ajax请求类型
type: 'GET',
//指定响应体的类型
dataType: 'json',
//设置超时时间
timeout: 2000,
//成功的回调
success: function(data){
console.log(data);
},
//失败的回调
error: function(e){
console.log(e);
},
//设置头部信息
headers: {
a: 200
}
})
})
fetch函数发送ajax请求
fetch('http://127.0.0.1:8000/fetch?test=ok',
{
//请求方法
method: 'POST',
//请求头
headers: {
name: 'Da'
},
//请求体
body: 'username=tri4123'
}).then((response)=>{
console.log(response);
return response.text();
//可以自动解析响应体为JSON格式的数据
// return response.json();
}).then((response=>{
console.log(response);
})
);
跨域
同源策略:协议、域名、端口号 必须完全相同
违背同源策略的称之为跨域
解决跨域
使用具备跨域特性的标签:<img> <script> <link> <iframe>
-
使用jsonp:在前段定义处理函数,供后端调用
前端代码
//在前段设置处理函数,供后端调用 <script> //处理数据的函数 function handleData(data){ //获取result元素 var result = document.getElementById('result'); result.innerHTML = data.name; } </script> <!-- <script src="./jsonp.js"></script> --> <script src="http://127.0.0.1:8000/jsonp-server"></script>
后端代码
const express = require("express"); const app = express(); app.all('/jsonp-server',(request,response)=>{ var PersonInfo = { name: 'Lx' } //调用前端已经定义好的函数 //就能将后端数据跨域传给前端 response.end(`handleData(${JSON.stringify(PersonInfo)})`) // response.send('console.log("jsonp实验成功")') })
-
jquery(原理还是jsonp)
前端代码
//callback=? 参数是必须的,这会在前端注册一个函数 供后端调用 $.getJSON('http://127.0.0.1:8000/server?callback=?',function(){ //后端的数据.... })
后端代码
const express = require("express"); const app = express(); app.all('/server',(request,response)=>{ var PersonInfo = { name: 'Lx' } //获取在前端注册的callback函数 var callbackFunc = request.query.callback; //调用前端已经定义好的函数 //就能将后端数据跨域传给前端 response.end(`${callbackFunc}(${JSON.stringify(PersonInfo)})`); })
-
CORS 跨域资源共享 官方的跨域方案
CORS通过在服务端设置一个响应头告诉前端,该请求是否允许跨域,浏览器收到响应头后会对响应进行放行
后端代码
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
response.setHeader('Access-Control-Allow-Methods','*');