为什么会出现跨域问题
跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的。
浏览器的同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。
如果协议,端口和主机对于两个页面是相同的,则两个页面具有相同的源,否则就是不同源的。
解决跨域问题的方法:
1 flash (已经淘汰)
2 服务器代理中转
3 jsonp 是数据交换的协议
4 document.domain(针对基础域名相同的情况)
如
bj.58.com document.domain = 58.com
tj.58.com document.domain = 58.com
针对jsonp 解决跨域问题:
5 iframe 实现跨域
jsonp跨域原理:
1 web页面中拥有"src"属性的标签都拥有跨域的能力,比如<script> <image><iframe>
2 所以,我们将数据放到服务器上,并且数据为json格式,(因为js 可以轻松处理json数据)
3因为我们无法监控通过script 的src属性是否把数据获取完成,所以需要做一个处理
4实现定义好处理跨域获取数据的函数,如function doJSON(data){};
5用src获取数据的时候添加一个参数cb='doJSON'(服务端会根据参数cb的值返回对应的内容)
此内容为以cb对应的值doJSON为函数真实要传递的数据为函数的参数的一串字符 如doJSON('数据');
最简单的原理,例如:
var oScript= document.createElement('script'); oScript.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=Anderson_An&cb=fn'; document.body.appendChild(oScript); //声明请求数据成功后执行的函数 function fn(data){ console.log(data); }
ajax 与jsonp 的区别以及本质区别?
ajax 实现数据请求不能跨域,jsonp可以实现跨域获取数据
本质区别是两者实现的原理不同:ajax 是通过创建xmlHTTPRequest 来获取内容,
而jsonp 的实现原理是通过,动态的添加script标签,利用src属性调用js 脚本实现;
一个小栗子实现跨域获取百度智能输入提示的功能:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ padding: 0; margin: 0; } #box { margin: 100px; } #wd{ 400px; height: 40px; } #list{ display: none; 400px; border: 1px solid #ccc; } li{ list-style: none; padding: 5px; } a{ text-decoration: none; color: #333; } </style> </head> <body> <div id="box"> <input type="text" id="wd"> <ul id="list"></ul> </div> <script> var wd = document.getElementById('wd'); var oUl = document.getElementById('list'); wd.oninput = debounce(getUserAction, 100, false);//给输入绑定一个防抖事件 function debounce(func, wait, immediate) { var timer = null; var result; var debounced = function () { var _this = this; var argu = arguments; clearTimeout(timer); if(immediate) { if(!timer) func.apply(_this, argu); timer = setTimeout(function () { timer = null; }, wait) }else { timer = setTimeout(function () { func.apply(_this, argu); }, wait) } return result; } debounced.cancel = function () { clearTimeout(timer); timer = null; } return debounced; } function getUserAction() { if(wd.value) { var oScript = document.createElement('script');//创建一个script标签 oScript.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=' + wd.value +'&cb=doJson'; document.body.appendChild(oScript); document.body.removeChild(oScript); }else { oUl.style.display = 'none'; } } function doJson(data) { var dataList = data.s;//因为百度的提示字符保存在s下 oUl.innerHTML = ''; if(dataList.length == 0) { oUl.style.display = 'none'; }else { dataList.forEach(function(item, index) { var oLi = document.createElement('li'); var oA = document.createElement('a'); oA.href = 'https://www.baidu.com/s?wd=' + item; oA.innerText = item; oLi.appendChild(oA); oUl.appendChild(oLi); oUl.style.display = 'block'; }) } } </script> </body> </html>
另外iframe 实现跨域
创建iframe 引用src 时末尾加一个' # '后面跟对应的要传的值;
获取方式:location.hash 就可以获取