多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[toc] ## previously 在ajax请求中如果协议和端口号和当前的一样,那么是可以省略的 ``` var xhr = new XMLHttpRequest; xhr.open("get","data.txt",true); //注意不要加'/',加了'/'是从根目录开始找 xhr.onreadystatechange = function(){ if(xhr.readyState ===4 && xhr.status ==200){ console.log(xhr.responseText); } }; xhr.send(null); ``` ## 什么是JSONP JSONP和AJAX相同,都是客户端向服务器端发送请求,给服务器端传递内容 或则 从服务器端获取内容 的方式。 ### JSONP 和 AJAX 的区别 AJAX属于同源策略 JSONP属于非同源策略(跨域请求),实现跨域请求的方式有很多种,只不过JSONP是最常用的。 ### 区分同源和非同源 1)协议 2)域名或则IP 3)端口号 以上三部分完全相同属于同源策略,我们使用AJAX技术获取数据;只要有一个不一样,就属于非同源,我们一般使用JSONP获取数据 ### webstorm测试支持 WB(webstorm)在预览页面的时候会默认的创建一个本地虚拟的服务,端口号是63342 ## 原理 JSONP利用了script标签不管是否是同源还是非同源 在script的世界中,没有同源跨域这一说,只要你给我src属性中的地址就是一个合法的地址,script都可以把对应的内容请求回来 JSON就是利用了SCRIPT的这个原理 1)我们首先把需要请求数据的那个跨域的API数据接口的地址赋值给SCRIPT的SRC 2)把当前页面中的某一个函数名当做参数值传递给跨域请求数据的服务器(URL问号传参,一般是:?callback=fn) 3)服务器接收到你的请求后,需要进行特殊的处理,把你传递进来的函数名和它需要给你的数据拼接成一个字符串 例如:我们传递进去的函数名是fn,它准备好的数据是`fn({"name":"ahhh"})`->`我传递的函数名(需要给我们的数据)` 4)最后服务器把准备的数据以HTTP协议的形式返回给我们客户端,客户端发现其实就是让我们的fn执行,而且还给fn传递了一堆的数据,那些数据就是我们想要的 **So,如果对方服务器不支持的话,JSONP也无用** ``` <scirpt src="js/index.js"></script> //同源 <script src="http://ping.js.qq.com/ping.js"></script> ``` ``` <script> function(data){ console.log(data); } </script> <script src="http://xxx?callback=fn"></script> ``` ![](https://box.kancloud.cn/1c31ab7086c37fcf6b542e032e440f13_517x124.png) ![](https://box.kancloud.cn/c3424aa8a589a386f9a0dd0912d4c060_799x182.png) 返回的是`fn({...})`,也就是让函数执行了 ![](https://box.kancloud.cn/1e21711d335c57858d1a4803b6edb682_643x222.png) ### 服务端配合 ![](https://box.kancloud.cn/a0fc88c4a3f213d63fa639549a2511cb_738x333.png) ## jQueryのJSONP ``` $.ajax({ url:"data.txt" ,type:"get" ,dataType:"json" ,data:null ,async:true ,cache:false ,timeout:1000 //->超时,走error,一般设定为3000ms ,success:function(data){ console.log(data) } ,error:function(){ } }) ``` jQuery会帮我把数据抽离出来 ``` $.ajax({ url:"" // ,type:"get" ,dataType:"jsonp" ,success:function(data){ console.log(data); } }) ``` ![](https://box.kancloud.cn/bc668f981fa47ce51e7c9d57fcdd274c_770x149.png) 会自动生成随即,防止cache ![](https://box.kancloud.cn/7916ff57823f980ef88d2d9c184ca6fe_620x117.png) 另外JSONP都是GET&&异步请求的 也可以定义传递给服务器的函数名和形参名 ``` $.ajax({ ... jsonpCallback:"fn" //把函数名变为fn,原本是jquery+随即字符串 ,jsonp:"cb" //把传递函数名的那个形参callback变为cb }) ``` ![](https://box.kancloud.cn/8b3e9e97671bcd3df58f27aca9732073_764x147.png) ## 百度搜索案例 suggestion su?wd= ![](https://box.kancloud.cn/d2193bf6da31161679cdcb1cbf71484c_358x67.png) ![](https://box.kancloud.cn/e2e1b46636f74c52c1e057ef656e392f_738x214.png) 链接地址格式 s?word= ![](https://box.kancloud.cn/aed71defa7a00c12208a9afaa0287e9f_750x230.png) >**注意:** ajax封装的jsonp方法,success中的data直接就是我们想要的数据而不是拼接后的整个函数。 blur会先click而触发,这样的话就获取不到click到的那个li的内容,so应该用事件委托 ![](https://box.kancloud.cn/3ead29dd9f58d61ad8d161f3b8bd966f_621x194.png) ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>百度模糊搜索-珠峰培训</title> <style type="text/css"> * { margin: 0; padding: 0; font-family: "\5FAE\8F6F\96C5\9ED1", Helvetica, sans-serif; font-size: 14px; color: #424242; } ul, li { list-style: none; } input { display: block; outline: none; } html, body { width: 100%; height: 100%; } .search { margin: 20px auto; width: 300px; } .search input { padding: 0 5px; width: 288px; height: 35px; border: 1px solid green; } .searchList { display: none; width: 298px; border: 1px solid green; border-top: none; } .searchList li { padding-left: 5px; height: 35px; line-height: 35px; cursor: pointer; } .searchList li:hover { background: #eee; } </style> </head> <body> <div class="search"> <input type="text" id="searchInput"/> <ul class="searchList"> </ul> </div> <script type="text/javascript" src="js/jquery-1.11.3.min.js"></script> <script type="text/javascript"> $(function () { var $searchInput = $("#searchInput"), $search = $(".search"), $searchList = $search.children(".searchList"); //->光标进入文本框(或者是用户在输入的过程中),通过判断是否存在内容来控制列表区域的显示隐藏 $searchInput.on("focus keyup", function () { var val = $(this).val().replace(/^ +| +$/g, ""); if (val.length > 0) { showList(); return; } $searchList.stop().slideUp(200); }); //->事件委托:点击的时候,如果事件源是文本框我们什么操作都不做处理,如果事件源是LI,我们让LI中的内容进入到文本框中,并且让列表区隐藏,如果事件源是其它的操作我们都要隐藏 $("body").on("click", function (e) { var tar = e.target, $tar = $(tar); if (tar.id === "searchInput") { return; } if (tar.tagName.toUpperCase() === "LI" && $tar.parent().hasClass("searchList")) { $searchList.stop().slideUp(200); $searchInput.val($tar.html()); return; } $searchList.stop().slideUp(200); }); //->根据输入内容的不一样,我们的列表区域显示不一样的内容 function showList() { var val = $searchInput.val().replace(/^ +| +$/g, ""); //->如果文本框中不存在内容的话,我们不需要在获取列表信息了 if (val.length === 0) { return; } //->通过JSONP跨域请求把我们输入内容所匹配回来的数据获取到 $.ajax({ url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + val, type: "get", dataType: "jsonp", jsonp: "cb", success: function (data) { var str = ''; if (data && data["s"]) { data = data["s"]; $.each(data, function (index, item) { if (index <= 3) { str += '<li>' + item + '</li>'; } }); } if (!str) {//->如果获取的数据一个都没有的话,我们直接的隐藏列表即可 $searchList.css("display", "none"); return; } $searchList.html(str).stop().slideDown(200); } }); } }); </script> </body> </html> ``` ## 其他跨域解决方案 ### Access-Control-Allow-Origin ![](https://box.kancloud.cn/ddda44d03d0d07be6c1f6aea97c436f3_964x409.png) `*`代表所有 ![](https://box.kancloud.cn/98fea737db383ce9399259523d554f63_789x167.png) ### 通过自身的后端代理 这说明了是浏览器器自身限制了跨域的请求 ![](https://box.kancloud.cn/ce5bc30a5f398093d0bf9915d465681b_604x270.png) ![](https://box.kancloud.cn/85b55a20a2b0120eb319e0c628435a33_491x335.png) ## 还有那些标签可以跨域 - link - img - script ## 关于script标签 不关心script中src的后缀名是什么,只要请求回来的东西能被js引擎解析即可(会被解析成js代码) ``` <script src="./test.txt"></script> ``` 相当于 ![](https://box.kancloud.cn/5e3a7971fc8f267dcc26d97759424f2e_382x205.png) 如果返回的数据不符合js解析语法会报错 ![](https://box.kancloud.cn/b5a28c6070cf5b5f113ab00b5b3b58d9_584x199.png)