前端开发笔记——Ajax与跨域(内附封装代码)

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)

    image-20220515145842511

解决跨域的方法二(前端框架处理(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)
			}
		}
	}
	
}

个人博客:www.fangqc.xyz

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值