常见问题:
- 什么是同源策略及限制
- 前后端如何通信
- 如何创建ajax
- 跨域通信的几种方式
同源策略:
定义:
- 源包括协议,域名,端口,只要有一个不一样就是不同的源
-
具体表现:
cookie,storage,indexDB无法读取
- DOM无法获得
-
前后端如何通信:
AJAX:同源通信
- websocket:不受同源策略的限制
- CORS:支持跨域通信和同源通信
如何创建一个ajax:
- xmlhttprequest对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
跨域通信的几种方式:
jsonp
- 原理:script标签的异步加载
如何实现:
- 客户端向服务端发起请求,并告诉服务器端callback的名称
<script src="http://www.baidu.com?data=name&callback=jsonpMethod"></script> - 后端返回一个jsonp函数
jsonpMethod({data:{}})
- 客户端向服务端发起请求,并告诉服务器端callback的名称
实现代码:
var util={}util.getName=function(prefix){return prefix+Math.random().toString(36).replace(/[^a-z]+/g,'').substr(0,5)}util.createScript=function(url,charset){var script=document.createElement('script')script.setAttribute('type','text/javascript')charset&&script.setAttribute('charset',charset)script.setAttribute('src',url)script.sync=truereturn script}util.jsonp=function(url, onsuccess, onerror, charset){// 告诉后端回调的名称var callbackName=util.getName('tt_player')// 在window注册一个全局callbackwindow[callbackName]=function(){if (onsuccess && util.isFunction(onsuccess)) {onsuccess(arguments[0]);}}// 动态创建一个script标签var script=util.createScript(url+'&callback='+callbackName,charset)// 判断标签是否加载成功script.onload=script.onreadystatechange=function(){if(!script.readyState||/loaded|complete/.test(script.readyState)){script.onload=script.onreadystatechange=null// 移除该script的DOM对象if(script.parentNode){script.parentNode.removeChild(script)}// 删除函数或变量window[callbackName]=null}}script.onerror=function(){if(this.onerror&&util.isFunction(onerror)){this.onerror()}}document.getElementsByTagName("head")[0].appendChild(script)}
hash
- 场景:当前页面A通过iframe嵌入了跨域的页面B
- 代码:
//A页面var B=document.getElementsByTagName('iframe')B.src=B.src+'#'+'data'//b页面添加以下代码window.onhashchange=function(){var data=window.location.hash}
postmessage
- 场景:窗口A向跨域的窗口B发送消息
- 代码(使用http-server在本地开启两个服务)
parent.html
<h1>父窗口</h1><iframe src="http://localhost:9001/child.html"width="500" height="100" frameborder="0"></iframe><button name="button" id="send">发信息给子窗口</button><script src="./parent.js"></script>
parent.js
window.addEventListener('message',function(data){this.console.log("我是父窗口,收到了子窗口发过来的消息","vs",data)},false)var btn=document.getElementById("send")btn.addEventListener('click',function(e){let child=document.querySelector("iframe").contentWindowchild.postMessage('这是父窗口发给你的信息','http://localhost:9001')})
child.html
<h1>我是子页面</h1><script src="./child.js" charset="utf-8"></script>
child.js
window.addEventListener('message',function(data){console.log(data)window.parent.postMessage('子窗口给父窗口回复','http://localhost:9002')},false)
websocket
var ws=new WebSocket('wss://echo.websocket.org')//ws是非加密,wss是加密ws.onopen=function(ev){console.log("connection 开始")ws.send('hello WebSockets!!!')}ws.onmessage=function(ev){console.log("收到消息"+ev.data)}ws.onclose=function(ev){console.log("connection 关闭")}
cors
fetch(url,{method:'get'}).then(function(res){//对响应res进行处理}).catch(function(err){//对错误进行处理})
- 需要服务器和浏览器同时支持
- 仅支持IE10以上浏览器
- 浏览器一旦发现ajax跨域请求资源,就会自动添加一些附加的头信息
- 实现CORS通信的关键是服务器,服务器实现了CORS接口,就可跨源通信
