Ajax学习记录
Ajax的作用
在不刷新页面的情况下请求数据,刷新局部页面。
XML介绍
用来传输、存储数据 和HTML的区别: 功能不同,HTML用来呈现数据 细节:XML全都是自定义标签,没有预定的标签
JSON介绍
“取代了XML”——老师曰 XML的一些劣势:在JS中不好处理,同时复杂的标签也浪费了数据传输
但是JSON到底是什么呢?看看百度的简述
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
JSON的本质就是个字符串
JSON和JS对象互相转换
JSON字符串转换为JS对象,使用 JSON.parse() 方法
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); // {a: 'Hello', b: 'World'}JS对象转换为JSON字符串,使用 JSON.stringify() 方法
var json = JSON.stringify({a: 'Hello', b: 'World'}); //'{"a": "Hello", "b": "World"}'
具体的使用方法 JSON详解
总之,这就是一个类似于Js对象的东西,用它来表示数据,用的时候当成一个对象,传输的时候当成一个字符串,简洁耐用。
Ajax特点
优点
- 在不刷新的情况下与服务器端进行通信
- 允许根据用户事件来更新局部页面
缺点
- 没有浏览历史
- 存在跨域问题
- SEO不友好(搜索引擎优化)
Ajax请求基本操作
前置说明,以下服务端采用了 Express 框架。使用它之前需要先引入并创建对象。
//引入express
const express = require('express');
//创建应用对象
const app = express();
});
GET
其中有一个属性xhr.readState表示的该Ajax请求所处在的状态,其值为[0,4],通常我们使用 4 。
- 0:请求未初始化,还没有调用 open()。
- 1:请求已经建立,但是还没有发送,还没有调用 send()。
- 2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
- 3:请求在处理中;通常响应中已有部分数据可用了,没有全部完成。
- 4:响应已完成;您可以获取并使用服务器的响应了。
发送一个GET请求
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
}
}
}
}
对应的服务器端的响应
//引入express
const express = require('express');
//创建应用对象
const app = express();
//创建路由规则
app.get('/server',(request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 允许自定义请求头
response.setHeader('Access-Control-Allow-Headers','*');
response.send('Hello Ajax!');
});
POST
前端代码
const result = document.getElementById('result')
result.addEventListener('mouseover', function(){
//1. 创建对象
const xhr = new XMLHttpRequest()
//2. 初始化 设置类型与URL
xhr.open('POST', 'http://127.0.0.1:8000/server')
// 设置请求头
xhr.setRequestHeader("Content-Type", 'application/x-www-from-urlencoded')
//3. 发送
xhr.send('a=100&b=200&c=300')
// 4. 事件绑定
xhr.onreadystatechange = () => {
if (xhr.readyState ===4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理服务端返回的结果
result.innerHTML = xhr.response
}
}
}
})
服务端代码
app.all('/server',(request, response) => {
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
response.send('Hello Ajax!--post');
});
请求JSON数据
const result = document.getElementById('result')
window.onkeydown = () => {
const xhr = new XMLHttpRequest()
// 设置响应体数据的类型
// 如果未设置,需要手动转换数据为json类型
// 如果设置了,则无需转换
xhr.responseType = 'json'
//2. 初始化 设置类型与URL
xhr.open('POST', 'http://127.0.0.1:8000/json-server')
// 设置请求头
xhr.setRequestHeader("Content-Type", 'application/x-www-from-urlencoded')
//3. 发送
xhr.send()
// 4. 事件绑定
xhr.onreadystatechange = () => {
if (xhr.readyState ===4) {
if (xhr.status >= 200 && xhr.status < 300) {
// console.log(xhr.response)
// result.innerHTML = xhr.response
//let data = JSON.parse(xhr.response)
result.innerHTML = xhr.response.name
}
}
}
}
服务端代码
app.all('/json-server',(request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
const data = {
name: 'zx'
}
let str = JSON.stringify(data)
response.send(str);
});
超时与网络异常
// 超时设置
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = () => {
alert('network timeout!')
}
// 网络异常回调
xhr.onerror = () => {
alert('network error!')
}
服务端代码
app.get('/delay',(request, response) => {
response.setHeader('Access-Control-Allow-Origin','*');
setTimeout(() => {
response.send('delay biubiubiu');
}, 3000);
});
取消请求
btn.onclick = () => {
xhr.abort()
}
重复请求问题
目的:防止用户疯狂点击造成大量请求
方法:设置一个变量,判断当前是否有正在进行的请求
const btn = document.getElementsByTagName('button')[0]
const result = document.getElementById('result')
let x = null
// 标识变量
let isSending = false //是否正在发送Ajax请求
btn.onclick = () => {
if (isSending) x.abort()
x = new XMLHttpRequest()
isSending = true
x.open("GET", 'http://127.0.0.1:8000/delay')
x.send()
x.onreadystatechange = () => {
if (x.readyState === 4) {
isSending = false
}
}
}
同源策略
跨域是什么
何为同源? 何为跨域? Ajax只能在同源下发送请求
如何解决跨域
JSONP
JSON with Padding,是一个民间的跨域解决方案,只支持GET请求。它是利用HTML中存在一些天然具有跨域能力的标签,比如img、link、ifram、script
使用方法
<script>
handle = (data) => {
const result = document.getElementById('result')
result.innerHTML = data.name
}
</script>
<script src="http://127.0.0.1:8000/jsonp-server"></script>
// 服务端代码
app.all('/jsonp-server',(request, response) => {
//response.send('console.log("hello jsonp-server")')
const data = {
name: 'zx'
}
// 将数据转化为字符串
let str = JSON.stringify(data)
response.end(`handle(${str})`)
});
这里有个小点就是,script标签带回来的东西一定要是JavaScript代码,否则会报错,所以我们通过以上代码的形式,用一层JS封装了数据。
来看看一个实践
当输入框失焦后,从服务端返回验证信息
<script>
handle = (data) => {
console.log(data)
result.innerHTML = data.msg
}
const input = document.getElementById('username')
const result = document.getElementById('result')
input.onblur = () => {
let username = this.value
// 向服务端发送请求
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8000/check-username'
// 将 script 标签插入到文档中
document.body.appendChild(script)
}
</script>
//服务端代码
app.all('/check-username', (request, response) => {
const data = {
exist: 1,
msg: '用户名不可用'
}
let str = JSON.stringify(data)
response.end(`handle(${str})`)
})
CORS
Cross-Origin Resource Sharing,跨域资源共享。
CORS 是官方的跨域解决方案,特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理。
用起来其实很简单,只需要服务端加上三个响应头即可。
表示通配所有
app.get('/server',(request, response) => {
response.setHeader('Access-Control-Allow-Origin','*')
response.setHeader('Access-Control-Allow-Headers','*')
response.setHeader('Access-Control-Allow-Method','*')
response.send('Hello Ajax!--2');
});
以下是一些零碎的东西
HTTP介绍
两大内容 请求与响应
请求报文
- 行 GET / URL / HTTP/1.1
- 头 Host、Cookie、Content-type、User-Agent:
- 空行
- 体
响应报文
- 行 HTTP/1.1 200 OK
- 头 Content-Type、Content-length、Content-encoding
- 空行
- 体
Nodemon
小工具,当node.js服务文件修改时,自动重启服务
安装命令 npm install nodemon
启动服务 nodemon server.js
小坑:安装的时候一开始是用npm i nodemon,结果安装成功了却又用不了,显示没有这个东西,后来换成了npm install nodemon才能用。
简单查了一下,发现这俩东西还真有差别。详情请见 npm i 与 npm install 的区别
IE缓存问题
缓存了之前的Ajax请求结果,当服务端更新时,直接拿了本地的旧的结果
解决方法 URL中添加一个关于时间的参数,使得浏览器认为这是和过去不同的请求
xhr.open('GET', 'http://127.0.0.1:8000/ie?t='+Date.now())
2022.2.20 学习总结:目前在看视频学习,进度条在18/30,预计明天就能够学完了。
参考资料