文章目录
第一章 原生AJAX
1.1ajax简介
- 异步JS和XML
- 在浏览器中向服务器发送异步请求,无需刷新网页获取数据
- 提高网页加载速度,提高用户体验
- 是一种将现有标准组合在一起的新方式
1.2XML介绍
- 可扩展标记语言
- XML被设计用来传输和存储数据,HTML用来呈现数据
- XML全都是自定义标签,HTML都是预定义标签
- ajax数据交换使用XML,前端JS对收到的XML格式字符串进行解析提取数据,现在被JSON取代
1.3ajax特点
1.3.1优点
- 无需刷新页面就可与服务器端进行通信
- 与需根据用户事件更新部分页面内容
1.3.2缺点
- 无浏览历史,不能回退
- 存在跨域问题(如默认不能在a.com向b.com发送ajax请求)
- 对搜索引擎优化不友好,爬虫不能爬取ajax动态生成内容,只能爬取最开始HTTP响应体页面内容
1.4HTTP协议
-
hypertext transport protocol 超文本传输协议,规定了浏览器和万维网服务器之间互相通信的规则
-
请求报文格式与参数
请求行:请求类型如GET、POST等 URL路径 HTTP协议版本(1.1最多) 请求头:Host: baidu.com Cookie: name=ddd Content-type: application/x-www-form-urlencoded User-Agent: chrome 83 ... 空行 请求体:GET类型此处为空,POST这里可有内容
-
响应报文格式与参数
响应行:协议类型 状态码 状态字符串 响应头:Content-Type: text/html;charset=utf-8 Content-length: 2048 Content-encoding: gzip ... 空行 响应体:<html> </html>
1.5Node.js
- ajax应用的服务端
1.6express框架
-
基于Node.js平台的web开发框架
-
基本使用案例:
//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 端口监听中...") })
命令
node express基本使用.js
运行
1.7ajax请求的基本操作(案例)
-
server后端
app.get()
内参数设置:请求路径
- 召回函数
(request,response)=>{}
- 设置响应头允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
- 设置响应体
response.send('');
- 设置响应头允许跨域
- 召回函数
-
前端script
-
获取元素
-
绑定事件
-
编写事件处理程序
-
创建xhr对象
let xhr = new XMLHttpRequest()
-
初始化,设置请求方法和url,设置url参数 :url?后跟参数如a=1,用&并列参数(适用于GET)
xhr.open('GET','http://127.0.0.1:8000/server');
-
发送请求 ,如果是POST,请求体在send里直接设置,加’',内直接写入,格式自由
xhr.send();
-
监听
onreadystatechange
事件,处理服务器返回的结果xhr.response
,注意判断状态码xhr.onreadystatechange = function(){}
-
-
-
设置请求参数:
- GET类型,在
xhr.open()
函数中url后以?分隔,url?,后跟参数如a=1,用&并列参数 - POST类型,在
xhr.send()
函数内写’参数’,格式可以是'a=10&b=6'
,'a:100&b:20'
,'123456'
- GET类型,在
-
设置请求头
xhr.setRequestHeader('首部名字','首部值')
- 可以自定义首部,需要服务端设置返回首部
response.setHeader('Access-Control-Allow-Headers','*');
,为防止浏览器发送我们需要的请求前发送OPTIONS(无法获得响应),可以修改后端为app.all()
可以接受任意请求 - 一般会把身份校验相关信息放在头内,传递给服务器,服务器提取数据进行身份校验
-
服务端响应JSON数据的处理
-
服务端
- 定义数据对象
- 利用
JSON.stringify(data)
方法对数据进行字符串转换
-
客户端/前端
-
若手动对接收的字符串转换为对象,利用
JSON.parse(xhr.response)
方法app.all('/json-server', (request, response) => { //设置响应 //设置响应头,设置允许跨域 response.setHeader('Access-Control-Allow-Origin','*'); response.setHeader('Access-Control-Allow-Headers','*'); //响应一个数据 let data ={ name: 'ddd' } //对对象进行字符串转换 let str = JSON.stringify(data); //设置响应体 response.send(str); });
-
若自动转换接收的字符串为对象,创建ajax对象后设置响应体数据类型
xhr.responseType = 'json';
,之后xhr.response
就是一个对象<body> <!--在窗口内按下任意键盘按键则向服务端发送请求,服务端返回结果--> <div id="result"></div> <script> //绑定对象 let r = document.getElementById('result'); //绑定键盘按下事件 window.onkeydown = function () { // test // console.log('test') //创建ajax对象 let xhr = new XMLHttpRequest(); //设置响应体数据类型 xhr.responseType = 'json'; //初始化,设置请求类型和url 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){ //响应体放在盒子中 //r.innerHTML=xhr.response; //手动对数据进行转换,字符串转换为对象 // let data = JSON.parse(xhr.response); // // console.log(data); // r.innerHTML = data.name; //自动转换,利用xhr的属性设置响应体数据类型 r.innerHTML = xhr.response.name; } } } } </script> </body>
-
-
1.8ajax中IE缓存问题
-
概述:IE浏览器会对ajax请求结果做缓存,导致后续若有相同请求,返回本地缓存,不是服务器的最新数据,如果时效性要求高则不适应
-
解决:给请求添加时间戳
xhr.open("GET",'http://127.0.0.1:8000/ie?t='+Date.now());
1.9ajax请求超时和网络异常处理
- 超时设置
xhr.timeout
- 超时回调
xhr.ontimeout = function () {}
- 网络异常回调
xhr.onerror = function () {}
let xhr = new XMLHttpRequest();
//超时设置 2s没有返回结果就会cancel
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function () {
alert("网络异常,请稍后重试!!");
}
//网络异常回调
xhr.onerror = function () {
alert("你的网络似乎除了一些问题!");
}
xhr.open("GET",'http://127.0.0.1:8000/delay');
1.10ajax取消请求
手动在结果还未返回时取消请求调用abort()
let btns = document.querySelectorAll('button');
let x = null;
//点击第一个按键发送
btns[0].onclick = function () {
x = new XMLHttpRequest();
x.open("GET",'http://127.0.0.1:8000/delay');
x.send();
}
//点击第二个按键abort
btns[1].onclick = function () {
x.abort();
}
1.11ajax请求重复发送问题
客户端一直发送相同请求会使服务器压力过大,这时候可以考虑后续出现相同请求则取消前面没有完成的相同请求,这样就保证了始终只有一个请求。方法是利用标识变量
//获取元素对象
let btns = document.querySelectorAll('button');
let x = null;
//标识变量
let isSending = false;//是否正在发送AJAX请求
btns[0].onclick = function () {
if(isSending)x.abort();// 如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
//修改标识变量的值
isSending = true;
x.open("GET",'http://127.0.0.1:8000/delay');
x.send();
x.onreadystatechange = function () {
if(x.readyState === 4){
//修改标识变量
isSending = false;
}
}
}
第二章 Axios发送AJAX请求
2.1 axios简介
一个ajax工具库,是Vue和React推荐的ajax请求工具包
2.2axios特点
- 可以从浏览器发起ajax请求
- 可以从node.js发起http请求
- 支持Promise API
- 可以拦截请求和响应
- 可以转换请求和响应数据
- 可以取消请求
- 自动转换成JSON
- 客户端支持防护XSRF攻击
2.3axios发送请求
-
GET
-
POST
-
AJAX
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>axios 发送 ajax请求</title> <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script> <style></style> </head> <body> <button>GET</button> <button>POST</button> <button>AJAX</button> <script> const btns =document.querySelectorAll('button'); //配置baseURL axios.defaults.baseURL='http://127.0.0.1:8000'; btns[0].onclick = function () { //GET请求 axios.get('/axios-server',{ //url参数 params:{ id:100, vip:6 }, //请求头信息 headers:{ name:'ddd', age: 21 } }).then(value => { console.log(value); }) } btns[1].onclick = function () { axios.post('/axios-server',{ //请求体 username:'admin', password:'123' },{ //url params: { vip:100, id:3 }, //请求头参数 headers:{ height:165, weight:95 } }) } btns[2].onclick = function(){ axios({ //请求方法 method:'POST', //url url:'/axios-server', //url参数 params:{ id:10, level:40 }, //头信息 headers:{ a:100, b:200 }, //请求体参数 data:{ username:'admin', password:'123' } }).then(response =>{ console.log(response); //响应状态码 console.log(response.status); //响应状态字符串 console.log(response.statusText); //响应头信息 console.log(response.headers); //响应体 console.log(response.data); }) } </script> </body> </html>
-
fetch()
函数也可以发送ajax请求
第三章 跨域
3.1同源策略
-
浏览器的一种安全策略,ajax默认遵守
-
同源:协议、域名、端口号完全相同
-
当前网页url与其ajax请求目标资源的url需要协议、域名、端口号相同
-
违背同源策略就是跨域
-
跨域问题常有,因为单台服务器服务有上限,性能有瓶颈
3.2跨域的解决方法
3.2.1 JSONP
- JSON with Paadding 非官方的跨域解决方案,只支持get请求
- JSONP利用
<script>
标签的跨域能力发送请求(有的网页标签本身具有跨域能力,如:img link iframe script) - 原理:返回一个函数调用(返回JS代码,才能被解析),函数的参数就是客户端想收到的数据,让前端对此进行处理,函数需要前端提前声明
原生JSONP跨域实践
判断前端输入用户名是否存在
-
前端
<body> 用户名:<input type="text" id="username"> <p></p> <script> //获取input元素 const input = document.querySelector('input'); const p = document.querySelector('p'); //声明handle函数 function handle(data){ 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://127.0.0.1:9000/check-username'; //3.将script插入到文档中 document.body.appendChild(script); } </script> </body>
-
server
//检测用户名是否存在 app.all('/check-username',(request,response)=>{ //response.send(console.log('hello jsonp-server')); const data = { exist: 1, msg:'用户名已经存在' }; //数据转化为字符串 let str = JSON.stringify(data); //返回结果 response.end(`handle(${str})`); })
3.2.2 CORS
-
Cross-Origin Resource Sharing 跨域资源共享 官方跨域解决方案
-
特点:
- 完全在服务端进行处理,不需要客户端操作
- 支持get和post请求
- 新增一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
-
工作原理:服务器设置一个响应头告诉浏览器,该请求允许跨域,浏览器收到该响应后就会对响应放行
-
CORS的使用:添加响应头即可
//cors服务-server app.all('/cors-server',(request,response)=>{ //设置跨域响应头 response.setHeader("Access-Control-Allow-Origin","*"); response.send('hello CORS'); });