Ajax
URL
URL地址一般由三部分组成
- 客户端与服务端之间的通信协议
- 存有该资源的服务器名称
- 资源在服务器上具体存放位置
客户端与服务端通信过程 请求-处理-响应三个步骤
资源请求方式
客户端请求服务器,最常见get和post请求
get请求通常用于获取服务端资源
post请求通常用于向服务端提交数据
Ajax优缺点
优点:可以无需刷新页面而与服务器进行通信
允许你根据用户事件来更新部分页面内容
缺点:没有浏览历史,不能回退
存在跨域问题
SEO不友好
HTTP协议
超文本传输协议
请求报文:
行 POST /xxx HTTP/1.1
头 Host: xx
Cookie: xx
Content-type: xxx
User-Agent: xxx
空行
体 username=admin&password=123
响应报文
行 HTTP/1.1 200 OK
头 Content-type:
Content-length:
Content-encoding:
空行
体
一个简单页面接收响应数据的程序
页面代码
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<button>点击</button>
<div id="result"></div>
</body>
<script>
const btn = document.querySelector('button')
const box = document.querySelector('#result')
btn.onclick = function () {
const xhr = new XMLHttpRequest()
//xhr.open() 是 XMLHttpRequest 对象的一个方法,用于初始化一个 HTTP 请求
//有三个参数,分别是指定请求方法、URL、是否使用异步模式,默认true使用异步模式
xhr.open('GET', 'http://127.0.0.1:8000/server')
//xhr.send()会将请求发送给服务器
xhr.send()
//onreadystatechange是XMLHttpRequest对象提供的一个事件,当浏览器readyState开始改变就会触发这个事件
xhr.onreadystatechange = function () {
//readyState有5个状态值,0, 1, 2, 3, 4,4表示请求已完成
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)//响应体
box.innerHTML = xhr.response
}
}
}
}
</script>
js代码(用的Express框架)
//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')
})
//4.监听端口启动服务
app.listen(8000, () => {
console.log("服务器已启动,8000端口监听中...")
})
在Ajax设置url参数
在URL后面加问号参数的形式
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300')
post请求(和get差别不大,没有贴全部代码)
参数传递方式
xhr.send('a=100&b=200&c=300')
GET和POST区别
两者都是HTTP请求方法
- 参数传递方式不同:GET 请求将请求参数拼接在 URL 后面,而 POST 请求则将参数放在请求体中。因此,GET 请求参数可以直接在浏览器地址栏中显示,而 POST 请求参数则不会在地址栏中显示。
- 安全性不同:由于 GET 请求参数直接暴露在 URL 中,因此相较而言更不安全。POST 请求将参数放在请求体中,可以保证相对更高的安全性。
- 数据类型不同:GET 请求仅支持 ASCII 码字符集,而 POST 请求没有此限制,可以发送二进制数据或其他类型的数据。
- 缓存处理不同:GET 请求通常会被浏览器缓存下来,以便下一次访问同样的 URL 时可以更快地响应。POST 请求则不会缓存。
- 响应结果不同:GET 请求通常用于获取资源,返回的是资源内容;而 POST 请求通常用于进行数据提交、修改或删除等操作,返回的是操作结果。
服务器响应JSON数据
服务器要返回一个对象,首先要将对象转换为json数据格式,然后客户端接收到这个数据,可以有两种方法来将其响应到页面
- 用JSON的parse方法将字符串转换为对象,然后打印其中的属性
- XMLHttpRequest对象里面有一个responseType属性,设置为json后会自动将json数据转换为对象,就可以直接使用
<div></div>
<script>
const box = document.querySelector('div')
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(JSON.parse(xhr.response))
//可以通过JSON.parse方法把JSON字符串转成对象,再打印属性
// const obj = JSON.parse(xhr.response)
// box.innerHTML = obj.name
// console.log(xhr.response)
box.innerHTML = xhr.response.name
}
}
}
}
</script>
//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.send('Hello Ajax')
})
app.all('/json-server', (request, response) => {
//设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
const obj = {
name: '三三'
}
const arr = JSON.stringify(obj)
//设置响应体
response.send(arr)
})
//4.监听端口启动服务
app.listen(8000, () => {
console.log("服务器已启动,8000端口监听中...")
})
解决IE缓存问题
xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now())
请求超时网络异常情况
xhr.timeout表示从发送 AJAX 请求到接收响应数据最长等待的时间,如果在该时间内服务器还没有返回响应数据,则会触发 timeout 事件。
xhr.timeout = 2000
xhr.ontimeout = function () {
alert('网络异常,请稍后重试')
}
取消请求
用到XMLHttpRequest对象中的abort方法
abort方法用于取消当前正在处理的 AJAX 请求。具体来说,当调用该方法时,浏览器会立即中断当前请求,并触发 XMLHttpRequest 对象的 abort 事件。
<button>点击发送</button>
<button>点击取消</button>
<script>
const btn = document.querySelectorAll('button')
let xhr = null
btn[0].addEventListener('click', () => {
xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:8000/delay')
xhr.send()
})
btn[1].addEventListener('click', () => {
xhr.abort()
})
</script>
重复发送请求的问题
设置一个标识变量来判断目前是否正在有请求发送,然后进行取消和发送请求的处理
<button>发送请求</button>
<script>
const btn = document.querySelector('button')
let xhr = null
let isSending = false
btn.addEventListener('click', () => {
//如果正在发送则取消请求发送一个新的请求
if (isSending) xhr.abort()
xhr = new XMLHttpRequest()
isSending = true
xhr.open('GET', 'http://127.0.0.1:8000/delay')
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
isSending === false
}
}
})
</script>
axios发送请求
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
<script>
const btn = document.querySelectorAll('button')
//配置baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000'
btn[0].addEventListener('click', () => {
axios.get('/axios-server', {
//url参数
params: {
a: 1,
b: 2
},
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value)
})
})
btn[1].addEventListener('click', () => {
//post第二个参数是请求体,第三个参数是其他配置
axios.post('/axios-server', {
username: 'admin',
password: 123
},
{
//url参数
params: {
a: 1,
b: 2
},
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value)
})
})
btn[2].addEventListener('click', () => {
axios({
//请求方法
method: 'POST',
//url
url: '/axios-server',
//其它参数
params: {
a: 100,
b: 300
},
headers: {
uname: 'hi'
},
data: {
username: 'admin',
age: 30
}
}).then(response => {
console.log(response)
console.log(response.status)
})
})
</script>
fetch函数发送请求
<button>发送请求</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
fetch('http://127.00.1:8000/fetch-server', {
method: 'POST',
params: {
a: 100,
b: 300
},
headers: {
uname: 'hi'
},
body: 'username=admin&password=123'
}).then(response => {
// return response.text()//{"name":"三三"}
return response.json()//{name: '三三'}
}).then(response => {
console.log(response)
})
})
</script>
跨域
同源策略
客户端的url和请求服务端的url协议、域名、端口号必须完全相同
违背同源协议就是跨域
解决跨域问题
-
JSONP
JSONP是非官方的跨域解决方案,只支持get请求
它通过动态创建<script>标签来实现跨域请求和相应数据的获取。(它利用了浏览器允许加载不同域名下的JS文件的特性,将需要获取的数据以JS函数参数的形式返回给客户端,从而达到跨域目的
function jsonp(url, callback) {
var script = document.createElement('script');
script.src = url + '\&callback=' + callback;
document.body.appendChild(script);
}
jsonp('<http://example.com/api/getData?name=Tom&age=20>', 'handleResponse');
function handleResponse(data) {
console.log(data);
}
-
CORS
官方的解决跨域的方案,跨域资源共享
服务器通过设置响应头信息中的 Access-Control-Allow-Origin 属性,允许客户端跨域访问自己的资源