Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例相关的知识,希望对你有一定的参考价值。

1.Ajax 使用jQuery中的Ajax

使用以下三种方法:

$.get(参数,函数)方法。

$.post(url,{参数},函数)方法。

$.ajax({参数,…})调用jQuery中的Ajax。

修改register.html的文件代码,通过使用以下三个方法来操作:(注意cdn库的导入。)

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>register</title>
	<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
	<script type="text/javascript">

		window.onload = function(){
			var username = document.querySelector("#username");
			var email = document.querySelector("#email");
			var phone = document.querySelector("#phone");

			username.onblur = function(){
				var usernameValue = username.value;
				var type = "get";
				var url = "./server/checkUsername.php";
				var params = "uname="+usernameValue;
				var dateType = "text";

				$.ajax({
					url:url,
					data:{uname:usernameValue},
					dataType:"text",
					success:function(result){
						var username_result = document.querySelector("#username_result");
						if (result == "NO") {
							username_result.innerText = "user已经注册!!";
						}else{
							username_result.innerText = "user可以使用。";
						}
					}
				});

				// 测试$.get(参数,函数)方法。
				$.get(url+"?"+params,function(result){
					console.log(result);
				});
			}

			email.onblur = function(){
				var emailValue = email.value;

				var type = "post";
				var url = "./server/checkEmail.php";
				var params = "e="+ emailValue;
				var dataType = "text";

				$.ajax({
					type:type,
					url:url,
					data:{e:emailValue},
					dataType:"text",
					success:function(result){
						var email_result = document.querySelector("#email_result");
						if (result==0) {
							email_result.innerText = "邮箱可用";
						}else{
							email_result.innerText = "邮箱不可用";
						}
					}
				});
				
				//测试$.post(url,{参数},函数)
				$.post(url,{e:emailValue},function(result){
					console.log(result);
				});
			}

			phone.onblur = function(){
				var phoneValue = phone.value;
				var type = "post";
				var url = "./server/checkPhone.php";
				var params = "phonenumber="+phoneValue;
				var dataType = "json";

				$.ajax({
					type:type,
					url:url,
					data:{phonenumber:phoneValue},
					dataType:"json",
					success:function(result){
						var phone_result = document.querySelector("#phone_result")
						if (result.status == 0 ) {
							//代表手机号码可用
							phone_result.innerText = result.message.tips+","+result.message.phonefrom;
						}else if (result.status == 1) {
							//代表手机号码不可用
							phone_result.innerText = result.message;
						}
					}
				});

				$.post(url,{phonenumber:phoneValue},function(result){
					console.log(result);
				});
				
			}

		}
	</script>
</head>
<body>
	<h1>注册界面</h1>
	<form action="">
		用户名:<input type="text" id="username"><span id="username_result"></span><br>

		邮箱:<input type="text" id="email"><span id="email_result"></span><br>

		手机号码:<input type="text" id="phone"><span id="phone_result"></span>
	</form>
</body>
</html>

2.跨域和同源策略

1.同源策略

Ajax必须在同源的前提下,才能正常的获取数据。

同源必须满足三个条件:

1.协议相同。
2.域名相同。
3.端口号相同。默认端口号为80。

下图,修改了之前register.html中ajax的xhr.open()中url的参数内容,也就是非同源的报错信息:

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

2.跨域

1.外部JS和PHP文件实现跨域

如果我们一定要在非同源的状况下,来获取数据。,那就用到了跨域。

这里解释一下,Ajax是为了访问自己服务器的数据,而跨域是为了访问别人服务器的数据。

1.通过script中的src属性调用外部JS文件,实现跨域。
2.通过script中的src属性调用外部php文件,实现跨域。

举一个携带参数实现php文件的一个例子:

创建一个weather.html文件,内容如下:

注意顺序问题,f1函数要先被读取,才能被调用!!

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>天气</title>
	<!-- 注意顺序问题,f1函数要先被读取,才能被调用!! -->
	<script type="text/javascript">
		function f(data){
			console.log(data);
		}
	</script>
	<script type="text/javascript" src="./data.php?city=beijing"></script>
</head>
<body>

</body>
</html>

再创建一个data.php文件,内容如下:

<?php 
	$city = $_GET["city"];
	if ($city == "beijing") {
		echo "f('北京天气晴')";
	}else{
		echo "f('天气查询无')";
	}
 ?>

2.动态创建script标签和指定回调函数来实现跨域

创建一个动态的script的三个步骤如下:

就是使用代码创建script标签,定义好src,并添加到head标签下。

一定注意src属性的callback它的值和回调函数的值一样的!!!这样我们就可以修改回调函数的名称了。

		//第一步,定义动态script
		var script = document.createElement("script");
		//这里写了url路径和参数参数值格式,最后添加了一个callback来定义方法名。
		script.src = "url(路径)?参数=" + 参数值 + "&callback=fun";
		script.type = "text/javascript";

		//第二步,指定的回调函数
		window["fun"] = function(data){
			console.log(data);
		};
		
		//第三部,将script放到head元素下面。
		var head = document.querySelector("head");
		head.appendChild(script);

3.下面使用script和回调函数调用外部案例

调用淘宝搜索词服务器案例:
一定看好步骤一步步实施。

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>淘宝关键字</title>
	<script type="text/javascript">
		window.onload = function(){
			var btn = document.querySelector("#btn");
			btn.onclick = function(){
				var keywordValue = document.getElementById("keyword").value;
				console.log(keywordValue);
				var url =  "https://suggest.taobao.com/sug?q=java&callback=haha"; //淘宝服务器的url和参数,回调函数。

				var script = document.createElement("script");
				script.src = "https://suggest.taobao.com/sug?q="+keywordValue+"&callback=haha";

				window["haha"] = function(data){
					var liTag = "";
					for(var i=0;i<data.result.length;i++){
						var temp = data.result[i];
						var tempSug = temp[0];
						liTag += "<li>"+tempSug+"</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="请输入关键字">
	<input type="button" id="btn" value="查询">

	<ul>
		<li>1.</li>
		<li>2.</li>
		<li>3.</li>
		<li>4.</li>
		<li>5.</li>
		<li>6.</li>
	</ul>
</body>
</html>

调用百度搜索词服务器案例:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>百度关键字</title>
	<script type="text/javascript">
		window.onload = function(){
			var btn = document.querySelector("#btn");
			btn.onclick = function(){
				var keywordValue = document.getElementById("keyword").value;
				console.log(keywordValue);
				var url =  "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=java&cb=haha";  //百度关键词服务器的url,参数和回调函数。

				var script = document.createElement("script");
				script.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+keywordValue+"&cb=haha";

				window["haha"] = function(data){
					console.log(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="请输入关键字">
	<input type="button" id="btn" value="查询">

	<ul>
		<li>1.</li>
		<li>2.</li>
		<li>3.</li>
		<li>4.</li>
		<li>5.</li>
		<li>6.</li>
	</ul>
</body>
</html>

4.跨域的封装

就是将跨域的几个步骤封装到外部的一个JS文件当中,进行调用即可。

创建一个baidu_function.html文件

jsonp非常重要,包括使用jQuery的时候,多多区分注意!

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>百度关键字</title>
	<script type="text/javascript" src="myutils.js"></script>
	<script type="text/javascript">
		window.onload = function(){
			var btn = document.querySelector("#btn");
			btn.onclick = function(){
				var keywordValue = document.getElementById("keyword").value;
				console.log(keywordValue);

				kuayu({
					url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
					data:{wd:keywordValue},
					success:function(data){
						console.log(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;
						}
					},
					jsonp:"cb", //jsonp很重要记住!!!
					jsonpCallback:"haha"
				});
			};
		}
	</script>
</head>
<body>

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

	<ul>
		<li>1.</li>
		<li>2.</li>
		<li>3.</li>
		<li>4.</li>
		<li>5.</li>
		<li>6.</li>
	</ul>
</body>
</html>

在创建一个myutils.js文件:

function kuayu(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);
}

可以修改自己写的Ajax,用if语句,来区分同源和非同源,从而去执行。

所有封装起来的代码,都是直接可以使用的,对往后都是有很大帮助!

5.使用jQuery进行跨域

使用jQuery进行跨域和jQuery的同源代码差不多,只不过多了几个参数。

注意jsonp和jsonpCallback两个参数!!!,指定了datatype指定了jsonp就相当于指定跨域,动态创建script标签。

创建一个baidu_jQuery.html文件如下运行:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>百度关键字</title>
	<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
	<script type="text/javascript">
		window.onload = function(){
			var btn = document.querySelector("#btn");
			btn.onclick = function(){
				var keywordValue = document.getElementById("keyword").value;
				console.log(keywordValue);

				//使用jQuery来获得跨域的数据
				//这里的dataType:"jsonp",值必须是jsonp!!!才能实现跨域,否则就变成了之前正常的同源Ajax数据传输了。
				$.ajax({
					url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
					data:{wd:keywordValue},
					success:function(data){
						console.log(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;
						}
					},
					dataType:"jsonp",
					jsonp:"cb",
					jsonpCallback:"haha"
				});
			};
		}
	</script>
</head>
<body>

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

	<ul>
		<li>1.</li>
		<li>2.</li>
		<li>3.</li>
		<li>4.</li>
		<li>5.</li>
		<li>6.</li>
	</ul>
</body>
</html>

6.模板引擎的使用

模板引擎作用:将数据和模板结合起来生成html片段,而不是像以前一样以字符串的形式来组合html片段。

常见的模板引擎有很多,其中效率最高的模板引擎就是artTemplate,是腾讯公司的开源的模板引擎,在github上面可以下载到源代码。这里我使用了github上面的一个template-web.js文件。

artTemplate模板引擎使用主要四个步骤:

1.引入js文件。
2.定义模板。
3.将数据和模板结合起来生成html片段。
4.将html片段渲染到界面中。

下面使用template模板进行一个简单的例子:

一定要多看注释步骤!!

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>百度关键字</title>
	<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
	<script type="text/javascript" src="template-web.js"></script>
	<!-- 1.模板的type=text/html 2.给模板配一个id -->
	<script type="text/html" id="resultTemplate">
		<!-- 这里是each,不是echo!! -->
		<ul>
			{{each s as value i}}
				<li>
					<div>
						<span>结果{{i}}:</span>
						<span>{{value}}</span>
					</div>
				</li>
			{{/each}}
		</ul>
	</script>
	<script type="text/javascript">
		window.onload = function(){
			var btn = document.querySelector("#btn");
			btn.onclick = function(){
				var keywordValue = document.getElementById("keyword").value;
				console.log(keywordValue);

				//使用jQuery来获得跨域的数据
				//这里的dataType:"jsonp",值必须是jsonp!!!才能实现跨域,否则就变成了之前正常的同源Ajax数据传输了。
				$.ajax({
					url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
					data:{wd:keywordValue},
					success:function(data){
						console.log(data);

						//template方法的含义就是将数据和模板结合起来,生成html片段。
						var html = template("resultTemplate",data);
						console.log(html);

						var divTag = document.querySelector("#divResult");
						divTag.innerHTML = html;
						
					},
					dataType:"jsonp",//指定跨域,动态创建script标签。
					jsonp:"cb",
					jsonpCallback:"haha"
				});
			};
		}
	</script>
</head>
<body>

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

	<div id="divResult">
		
	</div>
</body>
</html>

7.artTemplate模板常用格式语法

定义template()方法。

多注意script的type="text/html"和id,以及data的属性,也就是键值中的键!!

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>案例一</title>
	<script type="text/javascript" src="template-web.js"></script>
	<script type="text/html" id="resultTemplate">
		
		<h1>{{title}}</h1>
		{{each books as value i}}
		<div>{{value}}</div>
		{{/each}}
	</script>
	<script type="text/javascript">
		window.onload = function(){
			var data = {
				title:'四大名著图书信息',
				books:['三国演义','水浒传','西游记','红楼梦']
			};
			var html = template("resultTemplate",data);
			var container = document.querySelector("#container");
			container.innerHTML = html;
		};
	</script>
</head>
<body>
	<div id="container">
		
	</div>
</body>
</html>

template模板,if的使用:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>案例二</title>
	<script type="text/javascript" src="template-web.js"></script>
	<script type="text/html" id="test">
		{{if isAdmin}}
			<h1>{{title}}</h1>
			<h2>一共有{{count}}条数据</h2>
			<ul>
				{{each list as value i}}
					<li>索引 {{i + 1}} : {{value}}</li>
				{{/each}}
			</ul>
		{{/if}}

		{{if !isAdmin}}
			<h1>isAdmin是false!!</h1>
		{{/if}}
	</script>
	<script type="text/javascript">
		window.onload = function(){
				var data = {
					title:'条件判断基本粒子',
					isAdmin:true,
					list:['文艺','博客','摄影','电影','民谣','履行','吉他']
				};
				//这里的count与模板的count是相对应的。
				data.count = data.list.length;
				var html = template("test",data);
				var containor = document.querySelector("#content");
				containor.innerHTML = html;
		};
	</script>

</head>
<body>
	<div id="content">
		
	</div>
</body>
</html>

传递的data,本身就是一个数组的情况:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>案例三</title>
	<script type="text/javascript" src="template-web.js"></script>
	<script type="text/html" id="test">
		<ul>
			<!-- each的是键值的键!! -->
			{{each arr as value i}}
				<li>{{value}}</li>
			{{/each}}
		</ul>
	</script>
	<script type="text/javascript">
		window.onload = function(){
			//如果data本身就是一个数组,没有键值形式。
			var data = ['文艺','博客','摄影','电影','民谣','履行','吉他'];
			//所以这里需要创建一个temp来加入一个键值形式。
			var temp = {};
			//给temp传递一个arr属性!!
			temp.arr = data;
			var html = template("test",temp);
			document.querySelector("#content").innerHTML = html;
		}
	</script>

</head>
<body>

	<div id="content">
		
	</div>

</body>
</html>

使用#号来进行是否转义:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>案例四</title>
	<script type="text/javascript" src="template-web.js"></script>
	<script type="text/html" id="test">
		<!-- 使用#号来转义不转义 -->
		<p>不转义:{{#value}}</p>
		<p>默认转义:{{value}}</p>
	</script>
	<script type="text/javascript">
		window.onload = function(){
			var data = {
				//当数据中包含特殊字符。
				value:'<span style="color:#F00">hello!!</span>'
			};
			var html = template("test",data);
			document.getElementById('content').innerHTML = html;
		}
	</script>
</head>
<body>
	<div id="content"></div>
</body>
</html>

8.关于json一些注意事项

1.json格式

平时我们简单的一些\\u5317等等,如下图一样的格式,都是json格式,而这些\\u5317都是utf-8编码浏览器中显示的汉字。

对于json转换,可以在百度中搜索json格式,常用的有BEJSON等等。

注意:在转换JSON格式的时候,一定不要加入多余的东西,尤其是回调函数的名称!就是下图中的haha,只是haha里面的代码。

在这里插入图片描述

2.跨域返回jsonp,json

有时候调用Ajax的jsonp进行跨域,可能会报错:

返回jsonp格式,也就是返回的刚好是调用方法。

在这里插入图片描述

3.跨域得到的是一个json格式的字符串

如果跨域得到的是一个json格式的字符串,跨域是得不到相关的数据。当然非同源,ajax也是不可以的。

既然ajax和跨域都获取不到别人服务器的内容,那就可以使用自己的服务器来进行。

在这里插入图片描述
这里服务器代码配置,便是php后台人设计,理解就行。

以上是关于Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例的主要内容,如果未能解决你的问题,请参考以下文章

Ajax跨域Json跨域Socket跨域和Canvas跨域等同源策略限制的解决方法

21.跨域和CORS

跨域和CORS

JSONP跨域和CORS跨域的区别

百万年薪python之路 -- 请求跨域和CORS协议详解

rest_framework 跨域和CORS