Ajax-7. 跨域

同源策略

同源策略是浏览器的一种安全策略,所谓同源指的是请求URL地址中的协议、域名和端口号都相同,只要其中之一不相同就是跨域。

同源策略主要是为了保证浏览器的安全性

在同源策略下,浏览器不允许Ajax跨域获取服务器数据

说简单点:跨域是指从一个域名的网页去请求另一个域名的资源。只要协议、域名、端口有任何一个的不同,就被当作是跨域。

跨域的本质

Ajax 是为了访问自己服务器的数据,跨域是为了访问别人服务器的数据

跨域的本质:服务器返回了一个方法调用,这个方法是我们事先定义好的,而方法中的参数就是我们想要的数据。即script引入外部文件,这个文件的内容就是一个方法调用

引入外部 JS 文件

在这里插入图片描述

引入外部 php 文件

同理

动态创建 script 标签

// cityName 指动态输入的值
let cityName = document.querySelector("#city").value;
//动态创建script标签,动态制定src属性的值
let script = document.createElement("script");
script.src = "http://www.lisi.com/data.php?city=" + cityName;

let head = document.querySelector("head");
head.appendChild(script);

data.php 页面

<?php 
	$city = $_GET["city"];
	if($city == "beijing") {
		echo "foo('北京的天气晴')";
	}else {
		echo "foo('没有查询到天气信息')";
	}	
 ?>

test.html 页面

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<script type="text/javascript">
		function foo(data){
			console.log(data);
		}
	</script>
	<script type="text/javascript">
	window.onload = function(){
		let btn = document.querySelector("#btn");
		btn.onclick = function(){
			let cityName = document.querySelector("#city").value;
			//动态创建script标签,动态制定src属性的值
			let script = document.createElement("script");
			script.src = "http://www.lisi.com/data.php?city="+cityName;

			let head = document.querySelector("head");
			head.appendChild(script);

		};
	};
	</script>
</head>
<body>

	<h1>天气信息查询</h1>
	<input type="text" id="city" placeholder="请输入城市名称">
	<!-- <button id="btn">查询</button> -->
	<input type="button" id="btn" value="查询">
	
</body>
</html>

动态指定回调函数名称(前端界面决定方法名称)

<?php 
	$cbName = $_GET["callback"];
	$city = $_GET["city"];
	// 将方法名用.进行字符串的连接
	if($city == "beijing") {
		echo $cbName."('北京的天气晴')";
	}else {
		echo $cbName."('没有查询到天气信息')";
	}	
 ?>

test.html 页面

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	
	// 等待 data.php 返回具体内容的调用
	<script type="text/javascript">
		function foo(data){
			console.log(data);
		}
	</script>
	
	<script type="text/javascript">
	window.onload = function(){
		let btn = document.querySelector("#btn");
		btn.onclick = function(){
			let cityName = document.querySelector("#city").value;
			//动态创建script标签,动态制定src属性的值
			let script = document.createElement("script");
			script.src = "http://www.lisi.com/data.php?city="+cityName;

			let head = document.querySelector("head");
			head.appendChild(script);

		};
	};
	</script>
</head>
<body>

	<h1>天气信息查询</h1>
	<input type="text" id="city" placeholder="请输入城市名称">
	<!-- <button id="btn">查询</button> -->
	<input type="button" id="btn" value="查询">
	
</body>
</html>

给 window 增加属性进行方法定义

优化 test.html 页面

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<!-- <script type="text/javascript">
		function foo(data){
			console.log(data);
		}
	</script> -->
		<script type="text/javascript">
			window.onload = function() {
				var btn = document.querySelector("#btn");
				btn.onclick = function() {
					var cityName = document.querySelector("#city").value;
					//动态创建script标签,动态制定src属性的值
					var script = document.createElement("script");
					script.src = "http://www.lisi.com/data.php?city=" + cityName + "&callback=foo";
					
					// 给 window 增加了一个属性 foo ,这个属性是一个方法
					window["foo"] = function(data) {
						console.log(data);
					};

					var head = document.querySelector("head");
					head.appendChild(script);

				};
			};
		</script>
	</head>
	<body>

		<h1>天气信息查询</h1>
		<input type="text" id="city" placeholder="请输入城市名称">
		<button id="btn">查询</button>
	</body>
</html>

【淘宝提示词案例】

在这里插入图片描述
地址:https://suggest.taobao.com/sug

taobao_sug 页面

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<script type="text/javascript">
			window.onload = function() {
				let btn = document.querySelector("#btn");
				btn.onclick = function() {
					let keywordValue = document.querySelector("#keyword").value;
					console.log(keywordValue);

					let script = document.createElement("script");
					script.src = "https://suggest.taobao.com/sug?q=" + keywordValue + "&callback=fn1";
					window["fn1"] = function(data) {

						let liTag = "";
						for (let i = 0; i < data.result.length; i++) {
							let temp = data.result[i];
							let tempSug = temp[0];
							liTag += "<li>" + tempSug + "</li>";
						}

						let ulTag = document.querySelector("ul");
						ulTag.innerHTML = liTag;

					};
					let head = document.querySelector("head");
					head.appendChild(script);

				};
			};
		</script>

	</head>
	<body>

		<input type="text" id="keyword" placeholder="请输入相关的关键字">
		<button id="btn">查询</button>
		<ul>
			<!-- <li>1</li> -->
		</ul>

	</body>
</html>

演示图
在这里插入图片描述

【百度提示词案例】

在这里插入图片描述
地址:https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su

baidu_sug.html 页面

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Document</title>

		<script type="text/javascript">
			window.onload = function() {
				var btn = document.querySelector("#btn");
				btn.onclick = function() {
					var keywordValue = document.querySelector("#keyword").value;
					console.log(keywordValue);

					var script = document.createElement("script");
					script.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + keywordValue + "&cb=fn1";
					window["fn1"] = function(data) {

						var liTag = "";
						for (var i = 0; i < data.s.length; i++) {
							var temp = data.s[i];

							liTag += "<li>" + temp + "</li>";
						}

						var ulTag = document.querySelector("ul");
						ulTag.innerHTML = liTag;

					};
					var head = document.querySelector("head");
					head.appendChild(script);
				};
			};
		</script>

	</head>
	<body>

		<input type="text" id="keyword" placeholder="请输入相关的关键字">
		<button id="btn">查询</button>

		<ul>
			<!-- <li>1</li> -->
		</ul>

	</body>
</html>

自定义封装获取跨域数据

myajax.js

function myAjax(obj){
	let defaults = {
		type:"get",
		url:"#",
		data:{},
		success:function(data){},
		jsonp:"callback",
		jsonpCallback:"fn1"
	};

	for(let key in obj) {
		defaults[key] = obj[key];
	}

	let params = "";
	for(let 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);

	let script = document.createElement("script");
	script.src = defaults.url;

	window[defaults.jsonpCallback] = function(data){
		defaults.success(data);
	};

	let head = document.querySelector("head");
	head.appendChild(script);
}

修改后的百度提示词案例

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<script type="text/javascript" src="myajax.js"></script>
		<script type="text/javascript">
			window.onload = function() {
				var btn = document.querySelector("#btn");
				btn.onclick = function() {
					var keywordValue = document.querySelector("#keyword").value;
					// console.log(keywordValue);

					myAjax({
						url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
						data: {
							wd: keywordValue
						},
						success: function(data) {
							console.log(data);
						},
						jsonp: "cb",
						// jsonpCallback: "haha"
					});
				};
			};
		</script>

	</head>
	<body>

		<input type="text" id="keyword" placeholder="请输入相关的关键字">
		<button id="btn">查询</button>

		<ul>
			<!-- <li>1</li> -->
		</ul>

	</body>
</html>

使用 jQuery 获取跨域数据

dataType:"jsonp":一定要是 jsonp 格式
key 默认就是 callback

$.ajax({
	url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
	data: {
		wd: keywordValue
	},
	success: function(data) {
		console.log(data);
	},
	dataType: "jsonp",
	jsonp: "cb"
});

完善 myAjax() 方法

既可获取同源的数据,也可以获取跨域的数据。

function myAjax(obj){
	if(obj.dataType == "jsonp") {
		myAjax_Across(obj);
	} else {
		myAjax_Normal(obj);
	}

}
// 跨域获取数据
function myAjax_Across(obj){
	let defaults = {
		type:"get",
		url:"#",
		data:{},
		success:function(data){},
		jsonp:"callback",
		jsonpCallback:"fn1"
	};

	for(let key in obj) {
		defaults[key] = obj[key];
	}

	let params = "";
	for(let 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);

	let script = document.createElement("script");
	script.src = defaults.url;

	window[defaults.jsonpCallback] = function(data){
		defaults.success(data);
	};

	let head = document.querySelector("head");
	head.appendChild(script);
}
// 正常获取数据
function myAjax_Normal(obj) {
	let defaults = {
		type: "get",
		url: "#",
		dataType: "json",
		data: {},
		async: true,
		success: function(result) {
			console.log(result);
		}
	};

	//obj中的属性,覆盖到defaults中的属性
	//1、如果有一些属性只存在obj中,会给defaults中增加属性
	//2、如果有一些属性在obj和defaults中都存在,会将defaults中的默认值覆盖
	//3、如果有一些属性只在defaults中存在,在obj中不存在,这时候defaults中将保留预定义的默认值
	for (let key in obj) {
		defaults[key] = obj[key];
	}
	// 创建对象
	let xhr = null;
	if (window.XMLHttpRequest) {
		xhr = new XMLHttpRequest();
	} else {
		xhr = new ActiveXObject("Microsoft.XMLHTTP");
	}
	//得到params
	// data:{
	// 	uname:"zhangsan",
	// 	age:"18"
	// }//  uname=zhangsan&age=18
	let params = "";
	for (let attr in defaults.data) {
		params += attr + "=" + defaults.data[attr] + "&";
	}
	if (params) {
		params = params.substring(0, params.length - 1);
	}
	if (defaults.type == "get") {
		defaults.url += "?" + params;
	}
	// 准备发送
	xhr.open(defaults.type, defaults.url, defaults.async);
	// 执行发送
	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) {
					let 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) {
				let 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);
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡小多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值