Ajax
全称为 Asynchronous JavaScript And XML
,就是异步的 JS
和 XML
。
通过 Ajax
可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
Ajax
不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
XML
是可扩展标记语言,被设计用来传输和存储数据。
XML
和 HTML
类似,不同的是 HTML
中都是预定义标签,而 XML
中没有预定义标签,全都是自定义标签,用来表示一些数据。
xml<student>
<name>Tom</name>
<age>20</age>
<gender>男</gender>
</student>
JavaScript Object Notation
(JavaScript
对象表示法)
JSON
是存储和交换文本信息的语法,类似 XML
,比 XML
更小、更快,更易解析。
json{"student":{"name":"Tom","age":"20","gender":"男"}}
优点:
缺点:
执行npm init --yes
bashnpm i express
js// 引入express
const express = require('express')
// 创建应用对象
const app = express()
// 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response)=>{
response.send('Hello Express')
})
// 监听端口启动服务
app.listen(8001, ()=>{
console.log('服务已启动,端口号:8001')
})
bashnpm install -g nodemon
html页面
html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#result {
margin-top: 10px;
width: 200px;
height: 100px;
border: 2px solid #9900BB;
}
</style>
</head>
<body>
<button type="button">点击发送请求</button>
<div id="result"></div>
</body>
</html>
server.js
js// 引入express
const express = require('express')
// 创建应用对象
const app = express()
// 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response)=>{
// 设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('Hello Ajax')
})
// 监听端口启动服务
app.listen(8001, ()=>{
console.log('服务已启动,端口号:8001')
})
html<script type="text/javascript">
// 获取元素
const btn = document.getElementsByTagName('button')[0]
const result = document.getElementById('result')
// 绑定事件
btn.onclick = function() {
// 进行Ajax操作
// 1. 创建对象
const xhr = new XMLHttpRequest()
// 2. 初始化 设置请求方法和url
xhr.open('GET', 'http://localhost:8001/server')
// 3. 发送
xhr.send()
// 4. 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function() {
// 判断服务端返回了所有的结果(5个状态:0 1 2 3 4)
if(xhr.readyState === 4) {
// 判断响应状态码
// 2xx 成功
if(xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 空行 体
// console.log(xhr.status) // 状态码
// console.log(xhr.statusText) // 状态字符串
// console.log(xhr.getAllResponseHeaders()) // 所有响应头
// console.log(xhr.response) // 响应体
result.innerHTML = xhr.response
}
}
}
}
</script>
为GET请求设置参数:xhr.open('GET', 'http://localhost:8001/server?a=1&b=2&c=3')
分类 分类描述 1** 信息,服务器收到请求,需要请求者继续执行操作 2** 成功,操作被成功接收并处理 3** 重定向,需要进一步的操作以完成请求 4** 客户端错误,请求包含语法错误或无法完成请求 5** 服务器错误,服务器在处理请求的过程中发生了错误
需求:鼠标移入div框,发送POST请求,并在框中展示响应体
html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ajax POST请求</title>
<style type="text/css">
#result {
width: 200px;
height: 100px;
border: 2px solid #9900BB;
}
</style>
</head>
<body>
<div id="result"></div>
<script type="text/javascript">
const result = document.getElementById('result')
result.addEventListener('mouseover', function(){
// 1. 创建对象
const xhr = new XMLHttpRequest()
// 2. 初始化 设置请求类型和url
xhr.open('POST', 'http://localhost:8001/server')
// 3. 发送
xhr.send()
// 4. 事件绑定
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
// 处理服务端返回的结果
result.innerHTML = xhr.response
}
}
}
})
</script>
</body>
</html>
服务器端同时需要添加post方法:
jsapp.post('/server', (request, response)=>{
// 设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('Hello Ajax POST')
})
为POST请求设置参数:a=1&b=2&c=3')
,可以写任意类型任意格式,只要后端能够处理即可
设置请求头:
在send后写语句xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
当设置自定义请求头时,须在server.js中添加response.setHeader('Access-Control-Allow-Headers', '*')
,并将post方法改为all(即可以接收任意类型的请求)
需求:按下键盘按键,向服务端发送请求,服务端返回结果
服务器端设置
jsapp.all('/json-server', (request, response)=>{
// 设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应头,设置允许自定义请求头
response.setHeader('Access-Control-Allow-Headers', '*')
// 响应一个数据
const data = {
name: 'abc',
age: 12
}
// 对对象进行字符串转换
let str = JSON.stringify(data)
// 设置响应体
response.send(str) // send()只能接收str或buffer
})
手动转换数据
jsconst result = document.getElementById('result')
// 绑定键盘按下事件
window.onkeydown = function () {
// 1. 创建对象
const xhr = new XMLHttpRequest()
// 2. 初始化 设置请求方法和url
xhr.open('GET', 'http://localhost:8001/json-server')
// 3. 发送
xhr.send()
// 4. 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 手动对数据进行转换
let data = JSON.parse(xhr.response)
console.log(data)
result.innerHTML = data.name
}
}
}
}
自动转换数据
jsconst result = document.getElementById('result')
// 绑定键盘按下事件
window.onkeydown = function () {
// 1. 创建对象
const xhr = new XMLHttpRequest()
xhr.responseType = 'json'
// 2. 初始化 设置请求方法和url
xhr.open('GET', 'http://localhost:8001/json-server')
// 3. 发送
xhr.send()
// 4. 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 手动对数据进行转换
/* let data = JSON.parse(xhr.response)
console.log(data)
result.innerHTML = data.name */
// 自动转换
console.log(xhr.response)
result.innerHTML = xhr.response.name
}
}
}
}
使用时间戳来解决
jsxhr.open('GET', 'http://localhost:8001/ie?t=' + Date.now())
为server.js
设置延时响应
js// 延时响应
app.get('/time', (request, response)=>{
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(()=>{
response.send('延时响应')
}, 3000)
})
Ajax
处理请求超时和网络异常
js// 超时设置 2s
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = function() {
alert('请求超时,请稍后重试!')
}
// 网络异常回调
xhr.onerror = function() {
alert('网络好像开小差了')
}
html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>取消请求</title>
</head>
<body>
<button type="button">点击发送</button>
<button type="button">点击取消</button>
<script type="text/javascript">
const btns = document.querySelectorAll('button')
let xhr = null
btns[0].onclick = function() {
xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:8001/time')
xhr.send()
}
btns[1].onclick = function() {
xhr.abort()
}
</script>
</body>
</html>
频繁点击按钮时始终会发送请求,可能导致服务器压力较大等
jsconst btns = document.querySelectorAll('button')
let xhr = null
// 标识变量
let isSending = false // 是否正在发送ajax请求
btns[0].onclick = function() {
if(isSending) xhr.abort()
xhr = new XMLHttpRequest()
isSending = true
xhr.open('GET', 'http://localhost:8001/time')
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
isSending = false
}
}
}
server.js
js// jQuery服务
app.all('/jquery-server', (request, response)=>{
response.setHeader('Access-Control-Allow-Origin', '*')
const data = {
name: 'abc',
age: 12
}
// 对对象进行字符串转换
let str = JSON.stringify(data)
// 设置响应体
response.send(str) // send()只能接收str或buffer
})
client.html
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery 发送 AJAX 请求</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/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://localhost:8001/jquery-server', {a: 100, b: 200}, function(data) {
console.log(data)
}, 'json')
})
$('button').eq(1).click(function() {
$.post('http://localhost:8001/jquery-server', {a: 100, b: 200}, function(data) {
console.log(data)
})
})
</script>
</body>
</html>
js$('button').eq(2).click(function() {
$.ajax({
// url
url: 'http://localhost:8001/jquery-server',
// 参数
data: {a:100, b: 200},
// 请求类型
type: 'GET',
// 相应体结果
dataType: 'json',
// 成功的回调
success: function(data) {
console.log(data)
},
// 超时时间
timeout: 2000,
// 失败的回调
error: function() {
console.log('error')
},
// 头信息
headers: {c: 300, d: 400}
})
})
配置url根路径
jsaxios.defaults.baseURL = 'http://localhost:8001'
axios.get(url[, config])
参数为url
和配置信息
jsbtns[0].onclick = function() {
// GET 请求
axios.get('http://localhost:8001/axios-server', {
// url参数
params: {
id: 100,
vip: 7
},
// 请求头信息
headers: {
name: 'abc',
age: 18
}
}).then(value => {
console.log(value)
})
}
axios.post(url[, data[, config]])
参数为url
、请求体和配置信息
jsbtns[1].onclick = function() {
// POST请求
axios.post('http://localhost:8001/axios-server', {
user: 'admin',
password: 'admin'
}, {
// url参数
params: {
id: 300,
vip: 11
},
// 请求头信息
headers: {
name: 'abc',
age: 18
}
})
}
jsbtns[2].onclick = function () {
axios({
// 请求方法
method: 'POST',
// url
url: '/axios-server',
// url参数
params: {
vip: 13,
level: 2
},
// 头信息
headers: {
a: 241,
b: 21
},
// 请求体参数
data: {
user: 'admin',
password: '123456'
}
}).then(response => {
console.log(response)
// 响应状态码
console.log(response.status)
// 响应状态字符串
console.log(response.statusText)
// 响应头信息
console.log(response.headers)
// 响应体
console.log(response.data)
})
}
jsbtn.onclick = function() {
fetch('http://localhost:8001/fetch-server?vip=10', {
// 请求方法
method: 'POST',
// 请求头
headers: {
name: 'morales',
naa: 'abc'
},
// 请求体
body: 'username=admin&password=123456'
}).then(response => {
return response.text()
// return response.json()
}).then(response => {
console.log(response)
})
}
同源策略(Same-Origin Policy
)最早由 Netscape 公司提出,是浏览器的一种安全策略。
同源: 协议、域名、端口号 必须完全相同。
违背同源策略就是跨域。Ajax默认遵循同源策略。
示例:
server.js
jsconst express = require('express')
const app = express()
app.get('/home', (request, response) => {
// 响应一个页面
response.sendFile(__dirname + '/index.html')
})
app.get('/data', (request, response) => {
response.send('用户数据')
})
app.listen(8001, () => {
console.log('服务已启动')
})
index.html
HTML<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>同源策略</title>
</head>
<body>
<button type="button">获取用户数据</button>
<script type="text/javascript">
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>
</body>
</html>
JSONP
(JSON with Padding
),是一个非官方的跨域解决方案,只支持get请求
在网页有一些标签天生具有跨域能力,比如:img
、link
、iframe
、script
。JSONP
就是利用 script
标签的跨域能力来发送请求的。
js// jsonp服务
app.all('/jsonp-server', (request, response) => {
const data = {
name: 'absfe'
}
let str = JSON.stringify(data)
response.end(`handle(${str})`)
})
html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP解决跨域</title>
<style type="text/css">
#result {
width: 300px;
height: 100px;
border: #225588 1px solid;
background-color: aliceblue;
}
</style>
</head>
<body>
<div id="result"></div>
<script type="text/javascript">
function handle(data) {
const result = document.getElementById('result')
result.innerHTML = data.name
}
</script>
<script src="http://localhost:8001/jsonp-server" type="text/javascript" charset="utf-8"></script>
</body>
</html>
JSONP案例:检测用户名已存在
server.js
js// 用户名检测是否存在 app.all('/check-username', (request, response) => { const data = { exist: 1, msg: '用户名已经存在' } // 将数据转化为字符串 let str = JSON.stringify(data) // 返回结果 response.end(`handle(${str})`) })
username.html
html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>案例</title> </head> <body> 用户名:<input type="text" name="username" id="username" placeholder="请输入用户名" /> <p></p> <script type="text/javascript"> const input = document.getElementById('username') const p = document.querySelector('p') // 声明 handle 函数 function handle(data) { // 修改 input 框 input.style.border = "solid 1px #f00"; // 修改 p 标签的提示文本 p.innerHTML = data.msg; } // 绑定事件 input.onblur = function() { // 获取用户的输入值 let username = this.value; //向服务器端发送请求 检测用户名是否存在 // 1. 创建 script 标签 const script = document.createElement('script'); // 2. 设置标签的 src 属性 script.src = 'http://localhost:8001/check-username'; // 3. 将 script 插入到文档中 document.body.appendChild(script); } </script> </body> </html>
server.js
js// jquery-jsonp服务
app.all('/jquery-jsonp', (request, response) => {
const data = {
name: 'ati',
location: ['a', 'b', 'c']
}
// 接收 callback 参数
let cb = request.query.callback;
// 将数据转化为字符串
let str = JSON.stringify(data)
// 返回结果
response.end(`${cb}(${str})`)
})
index.html
html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery-JSONP</title>
<style>
#result {
width: 300px;
height: 100px;
border: solid 1px #089;
}
</style>
<script crossorigin="anonymous" src='https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js'></script>
</head>
<body>
<button>点击发送 jsonp 请求</button>
<div id="result"></div>
<script>
$('button').eq(0).click(function() {
$.getJSON('http://localhost:8001/jquery-jsonp?callback=?', function(data) {
$('#result').html(`
名称: ${data.name}<br>
位置: ${data.location}
`)
});
});
</script>
</body>
</html>
?callback=?
是固定写法
CORS
(Cross-Origin Resource Sharing
),跨域资源共享。CORS
是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get
和 post
请求。跨域资源共享标准新增了一组 HTTP
首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
CORS
是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
jsresponse.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", '*');
response.setHeader("Access-Control-Allow-Method", '*');
本文作者:Morales
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 License 许可协议。转载请注明出处!