Ajax笔记
简介
无刷新情况下向后端发送请求
XML
<student>
<name></name>
<age></age>
<gender></gender>
</student>
标签自定义
数据交互格式为XML,已经被JSON取代
特点
优点
- 无需刷新与服务器进行通信
- 根据用户事件更新部分内容
缺点
- 没有浏览历史,不能回退
- 存在跨域问题
- SEO不友好
HTTP协议
重点格式与参数
请求报文
行:请求类型(get、post等)、url路径、http协议版本
头:
Host:
Cookie:
Content-type:
User-agent:
空行
请求体:
若为get,为空;
若为post可以不为空
响应报文
行:http协议版本、响应状态码(400,403,401,500,200),响应状态字符串
头:
Content-type:
Content-length:
Content-encoding:
空行
请求体:
<html>
<head>
</head>
<body>
</body>
</html>
应用Node.js和express编写简单server.js
- express.js
// 1. 引入express
const express = require('express');
// 2. 创建应用对象
const app = express();
// 3. 创建路由规则
// request请求报文封装
// response响应报文封装
app.get('/', (request, response)=>{
// 设置响应
response.send('HELLO EXPRESS')
});
// 4. 监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动,8000端口监听中……")
})
- server.js
// 1. 引入express
const express = require('express')
// 2. 创建应用对象
const app = express()
// 3. 创建路由规则
// request请求报文封装
// response响应报文封装
app.get('/server', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.send('Hello Ajax')
})
app.post('/server', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
response.send('Hello Ajax POST')
})
app.all('/server', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
response.send('Hello Ajax POST')
})
app.all('/json-server', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const date = {
name: 'zdp'
}
let str = JSON.stringify(date)
response.send(str)
})
// 4-ie缓存问题:ie浏览器对ajax的返回作缓存,如果再次请求,只会返回缓存,对时效性较高的业务有影响
app.all('/ie', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.send('Hello Ajax IE 2')
})
app.all('/timeout', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(()=>{
response.send('Hello Ajax Timeout')
}, 3000)
})
// jquery服务
app.all('/jquery', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const date = {name:'zdp'}
response.send(JSON.stringify(date))
})
app.all('/axios', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const date = {name:'zdp'}
response.send(JSON.stringify(date))
})
app.all('/fetch', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const date = {name:'zdp'}
response.send(JSON.stringify(date))
})
app.all('/jsonp', (request, response)=>{
// 设置响应
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const data = {
name: 'zdp'
}
let str = JSON.stringify(data)
response.end(`handle(${str})`)
// response.send('console.log("hello")')
})
app.all('/check-username', (request, response)=>{
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
const data = {
exist:1,
msg: '用户名已经存在'
}
let str = JSON.stringify(data)
response.end(`handle(${str})`)
})
app.all('/jquery-jsonp', (request, response)=>{
const data = {
name: 'zdp',
city: ['北京', '上海',]
}
let cb = request.query.callback
let str = JSON.stringify(data)
response.end(`${cb}(${str})`)
})
app.all('/cors', (request, response)=>{
// 设置跨域
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
response.setHeader('Access-Control-Allow-Method', '*')
response.send("hello")
})
// 4. 监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动,8000端口监听中……")
})
原生Ajax
1-get.html
<!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;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
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?a=100&b=200&c=300');
xhr.send();
// readstate xhr对象属性
// 0 未初始化
// 1 open调用完毕
// 2 send调用完毕
// 3 服务端返回部分结果
// 4 服务端所有部分结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) { // 2开头都是成功的
// 处理结果
console.log(xhr.status)
console.log(xhr.statusText)
console.log(xhr.getAllResponseHeaders())
console.log(xhr.response)
result.innerHTML = xhr.response
}
}
}
}
</script>
</body>
</html>
2-post.html
<!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 #903;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.getElementById("result")
result.addEventListener("mouseover", function() {
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:8000/server')
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 自定义请求头,在server.js加一行
xhr.setRequestHeader('name', 'zdp')
xhr.send('a=100&b=200&c=300') // 设置参数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
3-json.html
<!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 #903;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.getElementById('result')
window.addEventListener('keyup', function() {
console.log("键盘")
const xhr = new XMLHttpRequest()
// 设置响应体数据类型
xhr.responseType = 'json'
xhr.open('GET', 'http://127.0.0.1:8000/json-server')
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 自定义请求头,在server.js加一行
xhr.setRequestHeader('name', 'zdp')
xhr.send('a=100&b=200&c=300') // 设置参数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// result.innerHTML = xhr.response
// 手动转换
// let date = JSON.parse(xhr.response)
// result.innerHTML = date.name
// 自动转换,需要设置response格式
result.innerHTML = xhr.response.name
}
}
}
})
</script>
</body>
</html>
4-ie缓存问题
<!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;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName('button')[0]
const result = document.querySelector('#result')
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest()
// ?增加参数,使ie浏览器认为不一样
xhr.open('GET', 'http://127.0.0.1:8000/ie?t='+Date.now());
xhr.send();
// readstate xhr对象属性
// 0 未初始化
// 1 open调用完毕
// 2 send调用完毕
// 3 服务端返回部分结果
// 4 服务端所有部分结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) { // 2开头都是成功的
// 处理结果
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
5-超时处理与网络异常
<!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;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName('button')[0]
const result = document.querySelector('#result')
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest()
// 超时设置
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = function(){
alert('网络超时,请稍后重试')
}
// 网络异常问题
xhr.onerror = function () {
alert("网络异常")
}
xhr.open('GET', 'http://127.0.0.1:8000/timeout');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) { // 2开头都是成功的
// 处理结果
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
6-取消请求.html
<!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>
</head>
<body>
<button>send</button>
<button>cancel</button>
<script>
const btns = document.querySelectorAll('button')
let x = null
btns[0].addEventListener('click', function() {
x = new XMLHttpRequest()
x.open('GET', 'http://127.0.0.1:8000/timeout')
x.send()
})
btns[1].addEventListener('click', function () {
x.abort()
})
</script>
</body>
</html>
7-重复请求处理.html
<!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>
</head>
<body>
<button>send</button>
<script>
const btns = document.querySelectorAll('button')
let x = null
let isSending = false;
btns[0].addEventListener('click', function() {
// 如果正在发送,则取消该请求,创建一个新请求
if (isSending) x.abort()
x = new XMLHttpRequest()
isSending = true
x.open('GET', 'http://127.0.0.1:8000/timeout')
x.send()
x.onreadystatechange = function(){
if (x.readyState === 4) {
isSending = false
}
}
})
</script>
</body>
</html>
fetch.html
<!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>
</head>
<body>
<button>Ajax请求</button>
<script>
const btn = document.querySelector('button')
btn.onclick = function () {
fetch('http://127.0.0.1:8000/fetch?vip=10', {
method: 'POST',
headers: {
a: 100
},
body: 'username=admin&password=admin'
}).then(response => {
console.log(response)
// return response.text();
return response.json();
}).then(response => {
console.log(response)
})
}
</script>
</body>
</html>
jquery-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>
<link crossorigin="anonymous" rel="stylesheet" href="./css/bootstrap-theme.min.css">
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/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">通用型方法Ajax</button>
</div>
<script>
$('button').eq(0).click(function(){
$.get('http://127.0.0.1:8000/jquery', {a:100, b:200}, function (date){
console.log(date.name)
}, 'json')
})
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jquery', {a:100, b:200}, function (date){
console.log(date)
})
})
$('button').eq(2).click(function(){
$.ajax({
// url:'http://127.0.0.1:8000/jquery',
url:'http://127.0.0.1:8000/timeout',
date:{a:100, b:200},
type: 'GET',
//响应体结构
dataType:'json',
success: function(date) {
console.log(date)
},
timeout: 2000,
error: function(){
console.log('出错!')
},
//自定义头信息
headers: {
c:300,
d:400
}
})
})
</script>
</body>
</html>
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 crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.3/axios.min.js"></script>
</head>
<body>
<button>GET</button>
<button>POST</button>
<button>Ajax</button>
<script>
const btns = document.querySelectorAll('button')
axios.defaults.baseURL = 'http://127.0.0.1:8000/'
btns[0].onclick = function () {
// get
axios.get('/axios', {
params: {
id:100,
vip:7
},
headers: {
name: 'zdp'
}
}).then(value => {
console.log(value)
})
}
btns[1].onclick = function () {
// post
axios.post('/axios', {
username: 'admin'
}, {
params: {
id:100,
vip:7
},
headers: {
name: 'zdp'
}
})
}
btns[2].onclick = function () {
axios({
method: 'POST',
url: '/axios',
params: {
vip: 10
},
headers: {
a: 100
},
data: {
username:'zdp'
}
}).then(response => {
console.log(response)
console.log(response.status)
console.log(response.headers)
console.log(response.data)
})
}
</script>
</body>
</html>
跨域问题
同源
协议、域名、端口号必须完全相同
Ajax遵循同源策略
- index.html
<!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>
</head>
<body>
<h1>zdp</h1>
<button>获取数据</button>
<script>
const btn = document.querySelector('button')
btn.onclick = function () {
const x = new XMLHttpRequest();
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>
</body>
</html>
- server.js
const express = require('express')
const app = express()
app.get('/home', (request, response)=>{
response.sendFile(__dirname + '/index.html')
})
app.get('/data', (request, response)=>{
response.send('Hello')
})
app.listen(9000, ()=>{
console.log("服务已经启动...")
})
跨域
违背同源策略就是跨域
jsonp
script标签本身是跨域的
script里src写上跨域js代码,返回函数调用js语句
- jsonp.html
<!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;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
function handle(data) {
const result = document.querySelector('#result')
result.innerHTML = data.name
}
</script>
<script src="http://127.0.0.1:8000/jsonp"></script>
</body>
</html>
- 创建script标签
<!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>
</head>
<body>
用户名:<input type="text" id="username">
<p></p>
<script>
const input = document.querySelector('input')
const p = document.querySelector('p')
function handle(data) {
input.style.border = "solid 1px #f00"
p.innerHTML = data.msg
}
input.onblur = function () {
let username = this.value
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8000/check-username'
document.body.appendChild(script)
}
</script>
</body>
</html>
- jquery.html
<!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 #089;
}
</style>
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
<button>发送</button>
<div id="result"></div>
<script>
$('button').eq(0).click(function () {
// callback必须填写
$.getJSON('http://127.0.0.1:8000/jquery-jsonp?callback=?', function (data) {
console.log(data)
$('#result').html(`
名称:${data.name}<br>
校区:${data.city}
`)
})
})
</script>
</body>
</html>
CORS
官方跨域解决方案
支持get,post
完全在服务端处理
<!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;
}
</style>
</head>
<body>
<button>send</button>
<div id="result"></div>
<script>
const btn = document.querySelector('button')
const result = document.querySelector('#result')
btn.onclick = function () {
const x = new XMLHttpRequest()
x.open('GET', 'http://127.0.0.1:8000/cors')
x.send()
x.onreadystatechange = function(){
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
console.log(x.response)
result.innerHTML = x.response
}
}
}
}
</script>
</body>
</html>