Ajax介绍
Ajax
全称为 Asynchronous JavaScript And XML
,就是异步的JS
和 XML
。
通过Ajax
可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
Ajax
不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
Ajax 优点:
1、可以无需刷新页面与服务器进行通信。
2、允许根据用户事件来局部更新页面内容。
Ajax缺点:
1、没有浏览历史,不能回退。
2、存在跨域问题。
3、SEO
不友好。
基本操作
//1、创建对象
const xhr = new XMLHttpRequest();
//设置响应体数据的类型
xhr.responseType = 'json';
//超时设置
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert('网络异常,请稍后重试!');
}
//网络异常回调
xhr.onerror = function() {
alert('你的网络似乎出了一些问题!');
}
//2、初始化,设置请求方法和url,在url后面跟问好直接传参
xhr.open('GET', 'http://127.0.0.1:3000/getTest?param1=test1¶m2=test2');
//设置请求头 (请求头的名字,请求头的值)
//如:Content-Type 设置参数查询字符串类型 (格式为param1=test1¶m2=test2)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//3、发送
//post请求的请求体要放在send()中,格式一般用json
//send(param1=test1¶m2=test2) | send(`${json字符串}`)
xhr.send();
//4、事件绑定,处理服务器端返回的结果
//readyState 是xhr的属性,表示请求的状态,共有5个值,分别是
//0:未初始化 1:open调用结束 2:send调用结束 3:服务端部分结果返回 4:全部结果返回
//onreadystatechange 为当状态改变时的回调函数
xhr.onreadystatechange = function() {
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) //响应体
}
}
}
其他方法
1、取消请求
//解决请求重复发送问题,减轻服务器压力
xhr.abort();
2、自定义请求头
除了预定义的请求头外,还可以设置自定义的请求头,比如 xhr.setRequestHeader('test', 'abc')
但是由于浏览器的安全机制会报错,需要服务端设置 Access-Control-Allow-Headers
为 *
,这时浏览器会发送一个 method
为 OPTIONS
的请求进行权限校验,所以要在服务端将接口的 method
改为 all
,可以接收任意类型的请求。
跨域问题解决办法
跨域: 同源策略(Same-Origin Policy
)是浏览器的一种安全策略,协议、域名、端口号必须完全相同,违背同源策略就是跨域。
解决:
-
JSONP
(JSON with Padding
):是一个非官方的解决方案,只支持get
请求。在网页中,有一些天生具有跨域能力的标签,比如:img
,link
,iframe
,script
。JSONP
就是利用script
标签的跨域能力来发送请求的。
先来看一个简单的demo
,想要把一个外部js
中的数据显示在页面上,可以这么做:
html代码:<div id="show"></div> <script> function handle(data){ let dom = document.getElementById('show'); dom.innerHTML = data.name; } </script> <script src="./app.js"></script>
app.js:
const data = { name: '张三' } handle(data);
app.js
就可以看作是服务端代码,服务器端返回结果的形式是一个函数调用,函数的实参就是想给客户端返回的结果数据,该函数在前端必须提前声明,否则会报错,这就是JSONP
实现跨域的原理。
下面是JSONP
实现的例子:客户端代码:
<button>发送</button> <div id="show"></div> <script> //需要提前声明接收数据的函数 function handle(data) { let dom = document.getElementById('show'); //拿到服务器端返回的数据展示在页面上 dom.innerHTML = data.name; } //点击按钮发送请求 let btn = document.querySelector('button'); btn.onclick = function() { //创建一个script标签 let script = document.createElement('script'); script.src = 'http://127.0.0.1:3000/getTest'; //将script标签插入到文档中 document.body.appendChild(script) } </script>
服务端代码:
const express = require('express'); const app = express(); app.get('/getTest', (request, response) => { //这是服务端实现跨域的解决方法,先不用 // response.setHeader('Access-Control-Allow-Origin', '*'); const data = { name: '张三' }; let str = JSON.stringify(data) response.end(`handle(${str})`) }); app.listen(3000, () => { console.log('3000服务已启动~~'); });
-
CORS
(Cross-Origin Resource Sharing
):跨域资源共享。CORS
是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持所有类型的请求。跨域资源共享标准新增了一组HTTP
首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
使用: 通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。response.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:3000'); //放行的网页url response.setHeader('Access-Control-Allow-Origin', '*'); //表示通配,所有网页都放行
-
使用代理服务器
vue-cli
解决办法:
其他:
最全跨域方案可以看这个大佬的总结:
https://segmentfault.com/a/1190000011145364
跨域解决方案
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域