Ajax与跨域
一、Ajax
AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- ajax获取服务器数据条件(同源数据):协议一样,域名相同,端口号相同。
创建步骤
1、创建 XMLHttpRequest 对象以及浏览器适配
var xhr = null;
if(window.XMLHttpRequest){
xhr =new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
2、 向服务器发送请求
var params="";
for (var attr in defaults.data){
params+=attr+"="+defaults.data[attr]+"&";
}
if(params){
params = params.substring(0,params.length-1);
}
if(defaults.type =="get"){
xhr.send(null);
}else if(defaults.type =="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(params);
}
3、 服务器 响应
//获得字符串形式的响应数据。
result=xhr.responseXML
//获得 XML 形式的响应数据
result=xhr.responseText;
result=JSON.parse(result)
4、onreadystatechange 事件
readyState的值分别代表:
- 0: 请求未初始化
- 1: 服务器连接已建立
- 2: 请求已接收
- 3: 请求处理中
- 4: 请求已完成,且响应已就绪
xhr.onreadystatechange = function(){
if(xhr.readyState ==4){
if(xhr.status == 200){
var result=null;
if(defaults.dataType =="json"){
result=xhr.responseText;
result=JSON.parse(result);
}else if(defaults.dataType =="xml"){
result=xhr.responseXML;
}else{
result=xhr.responseText;
}
defaults.success(result)
}
}
};
Tips
- ie6以下浏览器需要兼容
- json格式 json.parse()转换为对象
- xml数据格式的解析example
二、跨域
产生跨域的原因:当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同。
- 跨域的本质:其实就是服务器返回了一个方法调用,这个方法是我们事先定义好的,而方法
中的参数就是我们想要的数据
解决跨域的方法一(jsonp):
- JSONP :特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
- js实现跨域请求
function myAjax4Across(obj){
var defaults={
type:"get",
url:"#",
data:{},
success:function(data){},
jsonp:"callback",
jsonpCallback:"haha"
};
for(var key in obj){
defaults[key]=obj[key];
}
var params="";
for(var attr in defaults.data){
params+=attr+"="+defaults.data[attr]+"&";
}
if(params){
params = params.substring(0,params.length-1);
defaults.url+="?"+params;
}
defaults.url += "&"+defaults.jsonp+"="+defaults.jsonpCallback;
console.log(defaults.url);
var script = document.createElement("script");
script.src=defaults.url;
window[defaults.jsonpCallback] = function(data){
defaults.success(data);
}
var head = document.querySelector("head");
head.appendChild(script);
}
- JQ实现跨域请求(其中dataType必须为jsonp)
解决跨域的方法二(前端框架处理(vue)):
src / utils / request.js
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
// baseURL: 'http://127.0.0.1:8888/ruoyi',
baseURL: '/api',
// changeOrigin: true,
// 超时
timeout: 10000
})
vue.config.js
module.exports = {
devServer: {
// 自动打开浏览器
open: true,
port: 70,
proxy: {
// // detail: https://cli.vuejs.org/config/#devserver-proxy
'/api': {
target: `http://localhost:8888/ruoyi`,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
login.vue
import request from '@/utils/request'
// 获取验证码
export function getCodeImg() {
return request({
url: '/captcha/captchaImage?type=math',
method: 'get'
})
}
优点:
- 在浏览器中屏蔽了实际访问后端的 地址,相对安全
- 后端代码不必要进行额外处理跨域
缺点:
- 在浏览器中看不到后端访问的地址,开发阶段调试不太方便
解决跨域的方法三(SpringBoot后端进行处理):
在 每个 Controller 类上加入 @CrossOrigin 注解
或者
在 Controller的基类中加上 @CrossOrigin 注解然后其他 Controller 类就有了这个 @Controller
优点 :
- 使用起来简单,直接在Controller类上加 @CrossOrigin 注解即可
缺点:
- 如果后端技术使用的不是 SpringBoot,后端代码还需要处理跨域问题
- 浏览器直接访问 后端API,在某种程度上是不太安全的
解决跨域的方法四:
百度:Nginx
三、封装ajax (myutils.js)
function myAjax(obj){
if(obj.dataType == "jsonp"){
myAjax4Across(obj);
}else{
myAjax4Normal(obj);
}
}
// 跨域数据
function myAjax4Across(obj){
// 设置默认参数
//obj中的属性,覆盖到defaults中的属性
//1、如果有一些属性只存在obj中,会给defaults中增加属性
//2、如果一些属性在obj和defaults中都存在,会将defaults中的默认值覆盖
//3、如果有一些属性只在defaults中存在,在obj中不存在,这时defaults中将保留预定义的属性
var defaults={
type:"get",
url:"#",
data:{},
success:function(data){},
jsonp:"callback",
jsonpCallback:"haha"
};
for(var key in obj){
defaults[key]=obj[key];
}
var params="";
for(var attr in defaults.data){
params+=attr+"="+defaults.data[attr]+"&";
}
if(params){
params = params.substring(0,params.length-1);
defaults.url+="?"+params;
}
defaults.url += "&"+defaults.jsonp+"="+defaults.jsonpCallback;
console.log(defaults.url);
var script = document.createElement("script");
script.src=defaults.url;
window[defaults.jsonpCallback] = function(data){
defaults.success(data);
}
var head = document.querySelector("head");
head.appendChild(script);
}
//同源数据
function myAjax4Normal(obj){
var defaults={
type:"get",
url:"#",
dataType:"json",
data:{},
async:true,
success:function(data){console.log(result);}
};
for(var key in obj){
defaults[key]=obj[key];
}
var xhr = null;
if(window.XMLHttpRequest){
xhr =new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
//得到params
var params="";
for (var attr in defaults.data){
params+=attr+"="+defaults.data[attr]+"&";
}
if(params){
params = params.substring(0,params.length-1);
}
if(defaults.type =="get"){
xhr.send(null);
}else if(defaults.type =="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(params);
}
if(defaults.async){
xhr.onreadystatechange = function(){
if(xhr.readyState ==4){
if(xhr.status == 200){
var result=null;
if(defaults.dataType =="json"){
result=xhr.responseText;
result=JSON.parse(result);
}else if(defaults.dataType =="xml"){
result=xhr.responseXML;
}else{
result=xhr.responseText;
}
defaults.success(result)
}
}
};
}else{
if(xhr.readyState ==4){
if(xhr.status == 200){
var result=null;
if(defaults.dataType =="json"){
result=xhr.responseText;
result=JSON.parse(result);
}else if(defaults.dataType =="xml"){
result=xhr.responseXML;
}else{
result=xhr.responseText;
}
defaults.success(result)
}
}
}
}
博客:fangqc.xyz