Ajax基础
本文是我观看视频教程的笔记。 视频链接:https://www.bilibili.com/video/BV1WC4y1b78y?p=30
1 Ajax简介
全称:Asynchronous JavaScript And XML,即异步JS和XML。
通过Ajax可以在浏览器中向服务器发送异步请求,最大优势是:可以无刷新获取数据。
Ajax不是一门新的编程语言,而是将现有的标准组合在一起使用的新方式。
2 XML简介
XML是可扩展标记语言,被设计用来传输和存储数据。
XML和HTML类似,但是HTML中都是预定义的标签,XML中没有预定义标签,全都是自定义标签,用来表示一些数据。
比如有一个学生数据:
name=“小明”,age=18,gender=“男”
<student>
<name>小明</name>
<age>18</age>
<gender>男</gender>
</student>
如今XML已经基本被JSON所取代。
用JSON表示:
{"name"="小明","age"=18,"gender"="男"}
3 Ajax的特点
优点:
- 可以无需刷新就能跟服务器端进行通信
- 允许根据用户事件来更新部分页面内容
缺点:
- 没有浏览历史,不能回退
- 存在跨域问题(同源),不允许从一个服务向另一个服务发送请求
- SEO不友好,网页爬虫爬不到
4 HTTP请求报文与响应报文结构
请求报文
请求行:
GET/POST 路径 HTTP/1.1
请求头:
Host: baidu.com
Cookie: name=baidu
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行:固定的,必须要有
请求体:可有可无。GET请求的请求体为空,POST可以不为空
username=admin&&password=admin
响应报文
响应头:
HTTP/1.1 200 OK
响应头:
Content-type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
响应体:即HTML的内容
<html>
<head>
</head>
<body>
</body>
</html>
5 Chrome查看通信报文
示例:
Network -> 刷新页面 -> 点击Name中第一个 -> Headers-> Request Headers -> View source
GET请求中Query String Parameters中是对url参数进行格式化,可以方便调试。
POST请求中Form Data为提交的数据。
6 Express框架
const express=require('./node_modules/express')
const app=express();
app.get('/',(req,res)=>{
res.send('hello express');
});
app.listen(8000,()=>{
console.log("8000端口监听中");
})
浏览器输入127.0.0.1:8000,可以看到hello express
7 GET案例
案例说明
需求:点击按钮后将服务器返回的结果展示在div中。
案例准备
<button>点击发送请求</button>
<div id="result"></div>
#result {
width: 200px;
height: 100px;
border: 1px solid black;
}
const express=require('./node_modules/express')
const app=express();
app.get('/server',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*');
res.send('hello Ajax');
});
app.listen(8000,()=>{
console.log("8000端口监听中");
})
address already in use :::8000解决方法:vscode右下角选择占用了端口的项目并按ctrl+C禁用端口即可。
浏览器输入127.0.0.1:8000/server,可以看到hello Ajax,则案例准备完成。
案例代码
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById('result');
btn.onclick = function () {
const 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) {
result.innerHTML = xhr.response;
} else {
}
}
}
}
Ajax设置请求参数
在url后面追加 ?arg1=val1&arg2=val2…
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
8 POST案例
当鼠标移入框内时,向服务器发送POST请求,再将响应体在框内显示。(html和css文件与上面相同)
const result = document.getElementById('result')
result.addEventListener('mouseover', () => {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
})
在Node.js代码中加上
app.post('/server',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*');
res.send('hello Ajax POST');
});
鼠标移入可以看到 hello Ajax POST 显示。
POST设置参数
在send里面设置
xhr.send('a=100&b=200&c=300');
或者
xhr.send('a:100&b:200&c:300');
Ajax设置请求头信息
在open后面加上一行代码
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
9 Ajax响应JSON文件
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) {
result.innerHTML = xhr.response.name;
}
}
}
}
Node.js添加代码
app.all('/json-server',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*');
const data={
name:'hello json'
}
let str=JSON.stringify(data);
res.send('hello JSON');
});
10 nodemon
npm install -g nodemon
每次保存代码后可以自动重启服务端,非常方便
nodemon test.js
11 IE缓存问题
修改open中的url
xhr.open('GET','http://127.0.0.1:8000/server?t='+Date.now());
12 请求超时与网络异常处理
xhr.timeout = 2000;
xhr.ontimeout = function () {
alert('请求超时!');
}
xhr.onerror = function () {
alert('网络出问题了');
}
13 Ajax取消请求
调用 abort 方法。
案例
<button>点击发送</button>
<button>点击取消</button>
const btns = document.getElementsByTagName('button');
let xhr = null;
btns[0].onclick = function () {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
}
btns[1].onclick = function () {
xhr.abort();
}
14 Ajax请求重复发送问题
点击按钮后,先看看之前是否有相同的请求,如果有就把先前的请求取消掉。
const btn = document.getElementsByTagName('button')[0];
let xhr = null;
let isSending = false;
btn.onclick = function () {
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
isSending = true;
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
isSending = false;
}
}
}
15 JQuery发送Ajax请求
引入JQuery:https://www.bootcdn.cn/
<button>GET</button>
<button>POST</button>
<button>通用型方法ajax</button>
$('button').eq(0).click(function () {
$.get('http://127.0.0.1:8000/jq', { a: 100, b: 200 }, function (data) {
console.log(data);
}, 'json');
})
$('button').eq(1).click(function () {
$.post('http://127.0.0.1:8000/jq', { a: 100, b: 200 }, function (data) {
console.log(data);
}, 'json');
})
$('button').eq(2).click(function () {
$.ajax({
url: 'http://127.0.0.1:8000/jq',
data: { a: 100, b: 200 },
type: 'GET',
dataType: 'json',
timeout: 2000,
success: function (data) {
console.log(data);
},
error: function () {
console.log('出错了')
}
})
})
16 Axios发送Ajax请求
打开github.com/axios/axios,引入链接。
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btns[0].onclick = function () {
axios.get('/axios', {
params: {
a: 100,
b: 200
},
headers: {
name: 'xiaoming',
age: 20
}
}).then(value => {
console.log(value);
})
}
btns[1].onclick = function () {
axios.post('/axios', {
username: 'apple',
password: 'pass'
}, {
params: {
a: 100,
b: 200
},
headers: {
name: 'xiaoming',
age: 20
}
});
}
btns[2].onclick = function () {
axios({
method: 'POST',
url: '/axios',
params: {
vip: 10,
level: 30
},
headers: {
a: 100,
b: 200
},
data: {
username: 'admin',
password: 'admin'
}
}).then(res => {
console.log(res.status);
console.log(res.statusText);
console.log(res.headers);
console.log(res.data);
})
}
17 fetch发送Ajax请求
const btn = document.querySelectorAll('button')[0];
btn.onclick = function () {
fetch('http://127.0.0.1:8000/server', {
method: 'POST',
headers: {
name: 'baidu'
},
body: 'a=100&b=200'
}).then(res => {
return res.json();
}).then(res => {
console.log(res);
})
}
18 同源策略
同源策略是浏览器的一种安全策略。
同源:协议、域名、端口号必须完全相同。
违背通关策略就是跨域。Ajax默认支持同源策略。
同源案例:
const express=require('./node_modules/express')
const app=express();
app.get('/home',(res,req)=>{
req.sendFile(__dirname+'/index.html');
})
app.get('/data',(res,req)=>{
req.send('用户数据');
})
app.listen(9000,()=>{
console.log("9000端口监听中");
})
<h1>hello Ajax</h1>
<button>点击获取用户数据</button>
const btn = document.querySelector('button');
btn.onclick = function () {
const xhr = new XMLHttpRequest();
xhr.open('GET', '/data');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
}
}
}
}
19 JSONP的实现原理
JSONP((JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求。
JSONP工作原理:在网页有一些标签天生就具有跨域能力,比如img link iframe script等。JSONP就是利用script标签的跨域能力来发送请求的。
<script src="http://127.0.0.1:8000/jsonp"></script>
app.all('/jsonp',(req,res)=>{
res.send('console.log("hello jsonp")');
})
20 JSONP案例
案例需求:用户往文本框输入内容,然后失去焦点,发送内容,服务端返回一个"用户名存在"
用户名:<input type="text" id="username">
<p></p>
app.all('/jsonp',(req,res)=>{
const data={
exist:1,
msg:'用户名存在'
}
let str=JSON.stringify(data);
res.end(`handle(${str})`);
})
const input = document.querySelector('input');
const p = document.querySelector('p');
function handle(data) {
input.style.border = "1px solid black";
p.innerHTML = data.msg;
}
input.onblur = function () {
let username = this.value;
const script = document.createElement('script');
script.src = 'http://127.0.0.1:8000/jsonp'
document.body.appendChild(script);
}
21 JQuery发送JSONP请求
$('button').eq(0).click(function () {
$.getJSON('http://127.0.0.1:8000/jsonp?callback=?', function (data) {
console.log(data);
});
})
注意路径后面要加上"callback=?"
app.all('/jsonp',(req,res)=>{
const data={
name:'百度',
city:['北京','上海','深圳']
}
let str=JSON.stringify(data);
let cb=req.query.callback;
res.end(`${cb}(${str})`);
})
22 CORS
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权访问哪些资源。
app.all('/cors',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Headers','*');
res.setHeader('Access-Control-Allow-Method','*');
res.send('hello CORS');
})
|