学习目标
节数 | 知识点 | 要求 |
---|---|---|
第一节(原生Ajax封装) | 为什么函数封装 | 了解 |
封装思路 | 掌握 | |
封装ajax实现步骤 | 掌握 | |
第二节(什么是跨域) | 同源策略和非同源策略 | 掌握 |
跨域产生的原因 | 掌握 | |
第三节(跨域解决方案) | cors资源共享 | 掌握 |
后台代理 | 掌握 | |
jsonp原理以及实现 | 理解 | |
第四节(跨域实例练习) | 跨域获取百度搜索接口数据 | 掌握 |
模拟百度搜索 | 掌握 |
第一节 原生Ajax封装
1.1 封装函数
把共同的 同样的功能封装成一个函数 ,使用的时候 直接调用函数名就好了
()获取到当前的数据,return
<div id='div1'></div>
<div id='div2'></div>
<div id='div3'></div>
<div id='div4'></div>
<div id='div5'></div>
<script>
//JS获取div
var div1= document.getElementById('div1');
var div2= document.getElementById('div2');
var div3= document.getElementById('div3');
var div4= document.getElementById('div4');
function $(id){
return document.querySelector(id);
}
$('#div1');
1.2 Ajax封装
1.2.1 封装思路
1.封装函数 myAjax() 请求参数:请求方式 请求地址 请求数据 回调函数
2.myAjax({type:'',url:'',data:{},success:fun})
3.定义函数 function myAjax(jsonData)
4.函数 封装ajax 原生ajax:数据拼接 data='uname=qq&upsd=123'
get方式: open('get',url?data) send(null)
post方式:open('post',url) send(data)
1.2.2 原生的ajax请求
document.getElementById('btn').onclick=function(){
var name=document.getElementById('name').value;
var psd=document.getElementById('psd').value;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();//i7 主流浏览器都支持
}else if(window.ActiveXObject){
xhr = new ActiveXObject();//ie5 ie6
}
xhr.open('get','06get_json.php?uname='+name,true);
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
console.log(xhr.responseText);//返回xhr 字符串格式
console.log(JSON.parse(xhr.responseText));
}
}
}
1.2.3封装代码
document.getElementById('btn').onclick=function(){
var name=document.getElementById('name').value;
var psd=document.getElementById('psd').value;
myAjax({
type:’ get',
url:'05ajax.php',
data:{
uname:name,
upsd:psd
},
success:function(aa){
console.log(aa);
}
})
}
function myAjax(jsonData){
var xhr=new XMLHttpRequest();
var newData='';
if(jsonData.data){
var str='';
var arr=[];
for(var key in jsonData.data){
str=key+'='+jsonData.data[key];
arr.push(str);
}
newData=arr.join('&');//最终处理的数据拼接结果
}
if(jsonData.type.toLowerCase()=='get'){
xhr.open('get',jsonData.url+'?'+newData,true);
xhr.send();
} else if(jsonData.type.toLowerCase()=='post'){
xhr.open('post',jsonData.url,true);
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded;charset=utf-8');
xhr.send(newData);
}
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
jsonData.success(xhr.responseText);
}
}
}
}
本章作业
1.封装ajax
2.使用封装好的ajax请求一个本地的json文件,并渲染页面
第二节 什么是跨域
2.1 跨域问题产生的原因
浏览器安全问题:浏览器的同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。从一个域上加载的脚本不允许访问另外一个域的文档属性
当前的地址下去访问浏览器上另外一个地址,不允许我们访问,浏览器阻止我们访问,安全
跨域,指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。
跨域的严格一点来说就是只要协议,域名,端口有任何一个的不同,就被当作是跨域
访问游侠客旅游 分页网址:http://www.youxiake.com/search/line?keyword=&select=1&class_tab=0&area=0&day=1
【代码演示】
<script src='js/myAjax.js'></script>
<script>
myAjax({
type:'get',
url:' http://www.youxiake.com/search/line?keyword=&select=1&class_tab=0&area=0&day=1
',
success:function(res){
console.log(JSON.parse(res));
}
})
</script>
2.2 同源策略
同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当页面在执行一个脚本时会检查访问的资源是否同源,如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
2.3 为什么要跨域?
现实工作开发中经常会有跨域的情况,因为公司会有很多项目,也会有很多子域名,各个项目或者网站之间需要相互调用对方的资源,避免不了跨域请求。
本章作业
1.什么是同源策略
2.什么是跨域
第三节 跨域解决方案
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
3.1 后台代理
浏览器阻止跨域请求,利于后台去访问服务器资源,然后本地访问php后台返回的数据。
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
$.ajax({
type:'get',
url:'08houtai.php',
dataType:'json',
success:function(res){
console.log(res);
}
})
</script>
php文件:
$res=file_get_contents('http://www.youxiake.com/xxx ');
echo $res;
3.2 iframe跨域
1.)父窗口:(http://www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
2.)子窗口:(http://child.domain.com/b.html)
<script>
document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
</script>
3.3 跨域资源共享(CORS)
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置
CORS是一个W3C标准,全称是“跨域资源共享”(Cross-origin resource sharing)。
它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源发送请求的限制。
实现CORS主要在于服务器的设置,关键在于服务器HTTP响应报文首部的设置。前端部分大致还是跟原来发AJAX请求没什么区别,只是需要对AJAX进行一些相关的设置。
CORS的两种请求
浏览器将CORS分为两种请求,一种是简单请求,另外一种对应的肯定就是非简单请求
阮一峰:http://www.ruanyifeng.com/blog/2016/04/cors.html
3.4 porxy代理
原理:让代理服务器请求目标地址,因为请求是在服务端进行的,在服务端不存在跨域,从而解决跨域问题
实现:将原地址绑定在代理服务器下,让代理服务器发送请求。
3.5 jsonp跨域
3.5.1 jsonp跨域的原理
动态创建script标签,利用script标签的src属性可以获取任何域下的js脚本,通过这个特性(也可以说漏洞),服务器端不在返回json格式,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域
【代码演示】
<script>
function demo(res){//res形参 res后台返回给我的数据
console.log(res);
}
</script>
<script src='09jsonp.php?callback=demo'></script>
php:
<?php
//接收函数变量名
_GET['callback'];
//比如 虚拟数据 创建数组
$arr=array('msg'=>'ok','info'=>'虚拟后台数据');
arr);//数组--字符串对象
// $obj='hello';
echo "obj)";
?>
【代码演示】
<script>
function demo(res){
console.log(res);
}
</script>
<script src='http://suggestion.baidu.com/su?cb=demo&wd=ajax'></script>
3.5.2 不受同源限制的情况
当然也有不受同源限制的情况存在,主要有以下列举的:
\1. script
标签允许跨域嵌入脚本,稍后介绍的JSONP就是利用这个“漏洞”来实现。
\2. img
标签、link
标签、@font-face
不受跨域影响。
\3. video
和audio
嵌入的资源。
\4. iframe
载入的任何资源。(不是iframe之间的通信)
\5. 、
和``的插件。
\6. WebSocket
不受同源策略的限制。
本章作业
1.跨域的解决方式有哪几个
2.jsonp解决跨域的原理
第四节 jsonp跨域
4.1 百度jquery跨域请求
【语法】
$.ajax({
type: "get",
async: false,
url: "http://localhost:8080/getdata.php",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,标识jsonp回调函数名(一般为:callback)
jsonpCallback: "GetData",//callback的function名称
success: function (data) {
console.log(data);
},
error: function () {
alert('fail');
}
});
语法解析参数:
jsonp
:
在一个jsonp请求中重写回调函数的名字。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,
比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
jsonpCallback
:
为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。
这主要用来让jQuery生成一个独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理
【百度代码演示】
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
var val='爱';//input里面获取的
$.ajax({
type:'get',
url:'http://suggestion.baidu.com/su?wd=ajax',
dataType:'jsonp',//数据类型jsonp格式
jsonp:'cb',//定义回调函数参数名字 后台接收的函数名 默认callback 如果后台用的默认的 可以省略的
jsonpCallback:"demo",//可以省略: 默认:jquery随机数字()
success:function(res){
console.log(res);
}
})
</script>
4.2 jsonp优缺点
4.2.1优点
1.它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略
2.它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;
3.在请求完毕后可以通过调用callback的方式回传结果。
将回调方法的权限给了调用方。这个就相当于将controller层和view层终于分开了。
我提供的jsonp服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续view操作都由调用者来自己定义就好了。
如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,
逻辑都可以使用同 一个jsonp服务。
4.2.2 缺点
1它只支持GET请求而不支持POST等其它类型的HTTP请求
2它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
3 jsonp在调用失败的时候不会返回各种HTTP状态码。
4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。
那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。
于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。