第十周第二天笔记
2018-10-01 本文已影响0人
果木山
1 jsonp
1.1 script预解释
- 基础知识:
- 每一个script指的就是一个独立的域,不同的script代表不同的域;
- 两个不同的域之间函数的调用,必须使函数定义阶段的域先引入,然后函数调用的函数的域后引入;顺序相反不能拿到数据;
//1. 函数定义阶段的域先引入,函数执行阶段的域后引入,此时执行正确,弹出123; <body> <script> function fn() { alert(123); } </script> <script> fn(); </script> </body>
//2. 函数执行阶段的域先引入,函数定义阶段的域后引入,此时执行会报错,即:fn is not defined; <body> <script> fn(); </script> <script> function fn() { alert(123); } </script> </body>
1.2 jsonp原理
- jsonp原理体验:
- jsonp的原理:通过一个script建立一个独立的域,这个域的请求地址为百度的一个服务器,通过wd的值来查找数据,然后去将数据作为一个实参,传入到cb后面的函数中,执行cb后面函数名的函数;
- jsonp请求的实质是获取百度服务器中数据库中的数据,作为实参传入到全局函数中;获取数据的方式:在百度所搜框中输入文字后,在控制台中的network中会生成数据,然后找到带
su?wd=
的地址后,在新的页面中打开,就会看到数据;然后删除没用的地址数据;设置cb的值为全局函数名即可; - jsonp请求的三步:
- 定义一个有名字的全局函数,作为cd后面的函数名;
- 在全局函数中设置形参,获取实参数据;
- 通过script发送请求:通过script来创建一个域,src赋值中包括(url?参数&cb=函数名),在域中,执行cb后面的函数,给函数传入一个实参数据;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jsonp体验</title> </head> <body> <script> window["xhfd"]=function(data) { console.log(data); } </script> <!--请求步骤:在url这个请求地址中,通过wd后面的赋值来进行查找,查找到的数据作为实参传入到cb后面的函数中执行--> <script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=zhouxingchi&cb=xhfd"></script> </body> </html>
2 ajax封装
- jQuery中ajax体验
- 注意:在百度服务器中搜索获取地址后,向一个函数中传入实参数据,执行函数,必须设置jsonp参数为cb,cb设置的函数名为默认的jQuery...;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jQuery中jsonp体验</title> </head> <body> <script src="jquery.js"></script> <script> //https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=zhouxingchi&cb=xxx //分析:问号之前的为请求地址;wd等号后为搜索的内容;cd后面为调用函数的函数名; $.ajax({ url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",//请求地址;后台接口 data:{"wd":"扶摇"},//前端传给后台的数据,可有可无的; type:"get",//请求方式,post,get,jsonp可有可无,如果写了jsonp,没写默认的都是get; dataType: "jsonp",//返回的数据类型,可有可无的,如果传了,拿到的数据就是josn对象,如果没有,拿到的是字符串 jsonp:"cb",//可有可无,没有,默认是callback;但在百度服务器中搜索必须设置为cb fnLoading:function(){//等待加载 console.log("数据正在加载中,请耐心等待"); }, complete:function(){//加载完成 console.log("数据请求结束") }, success:function(data){//数据请求成功 console.log(data); }, error:function (data) {//数据请求失败 //数据请求失败的处理; }, timeout:2000//请求超时,可有可无,没传默认3000; }) </script> </body> </html>
- 封装myAjax函数
- 参数:ajax({url:xxx,data:xxx,type:xxx,dataType:xxx,jsonp:xxx,fnLoading:xxx,complete:xxx,success:xxx,error:xxx,timeout});
- 思路:
- 获取参数;
- 获取数据的四步
- 创建一个xml对象:需注意的是IE6浏览器下不兼容,需要做兼容处理
- 打开地址
- 发送请求
- 通过switch来创建不同情况下的设置
- get请求:参数在地址中,在url?的后面,以键值对的形式连接;
- post请求:参数在请求体中,地址url后面不跟参数;
- jsonp请求:与get和post两种形式不同,独立设置
- jsonp请求的步骤
- 新建一个全局变量,作为函数名,注意函数名中不能存在小数点;
- 创建一个全局函数,函数中设置形参,用于获取实参;
- 新建一个script标签,插入到body的最后面,用于发送请求,其中src值的形式为:url?参数&cb=函数名
- 响应请求
- 响应请求前可以添加fnLoading函数;
- 添加请求事件后判断
xml.readyState===4
成立后,代表请求成功,可以设置执行complete函数; - 通过正则校验xml.status的状态码是否为2xx
- 如果校验成功,代表响应成功,执行success函数;执行函数前,判断需要返回的类型,然后传入响应的实参给函数;
- 如果校验失败,则返回状态码给error函数;
- 添加等待超时判断
- 添加定时器,判断在指定timeout时间内,是否响应成功,如果未成功,执行定时器函数,弹出信息;
- 注:在定时器前面判断是否为jsonp执行,如果是的话,阻断程序执行,不执行定时器;
- 注意:
- 使用时,设置对象中的属性data时,用对象的形式设置;利用json2url函数,将对象转换为字符串格式为"key=val&key=val"形式;
- 封装的get和post只能在本地获取数据,不能跨域获取;跨域获取用jsonp请求;
- 代码:
- 执行代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>封装的ajax</title> </head> <body> <script src="JS/ajax.js"></script> <script> myAjax({ url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su", data:{wd:"zhouxingchi"}, type:"jsonp", dataType:"json", jsonp:"cb",//此处必须设置jsonp为cb,才能使用 success:function (data) { console.log(data); } }); </script> </body> </html>
- 封装JS代码:
//参数:ajax({url:xxx,data:xxx,type:xxx,dataType:xxx,jsonp:xxx,fnLoading:xxx,complete:xxx,success:xxx,error:xxx,timeout}) //将对象中的属性名和属性值转化为key=val&key=val的形式 function json2url(obj) { //参数:对象,返回值:字符串 //思路:对象-数组-字符串 obj.t=Math.random();//避免缓存 var ary=[]; //遍历对象 for(var attr in obj){ ary.push(attr+"="+obj[attr]); } return ary.join("&"); } function jsonParse(strJson) { return "JSON" in window?JSON.parse(strJson):eval("("+strJson+")"); } function myAjax(json) { json=json||{}; //如果json中请求地址url不存在 if(!json.url) return; //参数获取 var url=json.url; //data属性值为一个对象,对象中为参数 var data=json.data||{}; var type=json.type||"get"; var jsonp=json.jsonp||"callback"; var timeout=json.timeout||3000; var timer=null; //四步: //1 创建一个xml对象 //每个类函数都是window的一个属性; if(window.XMLHttpRequest){ var xml=new XMLHttpRequest(); }else{//IE6兼容处理 var xml=new ActiveXObject("Microsoft.XMLHTTP"); } //2 打开地址;3 发送请求 //get请求:参数在地址中,在url?的后面,以键值对的形式连接; //post请求:参数在请求体中,地址url后面不跟参数; switch(type.toLowerCase()){ case "get": xml.open("get",url+"?"+json2url(data),true); xml.send(null); break; case "post": xml.open("post",url,true); xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xml.send(json2url(data)); break; case "jsonp": //新建一个全局函数 var kbfd="jsonp_"+Math.random(); kbfd=kbfd.replace(".","");//函数名中不能存在小数点,所以需要替换 window[kbfd]=function (data) { json.success && json.success(data); //卸磨杀驴,干掉script document.body.removeChild(oS); //将oS赋值为null; oS=null; }; data[jsonp]=kbfd; //创建script标签,设置其src,通过script发送请求 var oS=document.createElement("script"); //script中src包含url?参数&cb=kbfd oS.src=url+"?"+json2url(data); //script必须插入到页面的底部 document.body.appendChild(oS); break; } //响应请求之前的准备 json.fnLoading && json.fnLoading(); //4 响应请求 xml.onreadystatechange=function () { if(xml.readyState===4){ //请求成功 json.complete && json.complete(); clearTimeout(timer); //判断后台响应成功还是失败; if(/^2\d{2}$/.test(xml.status)){//响应成功 if(json.dataType==="json"){ json.success && json.success(jsonParse(xml.responseText)); }else{ json.success && json.success(xml.responseText); } }else{//响应失败 json.error && json.error(xml.status); } } }; if(type==="jsonp") return; //5 等待超时 timer=setTimeout(function () { alert("您的网络不行啊"); xml.onreadystatechange=null; },timeout); }
- 知识点
- 类是window的属性