常见问题:
- 什么是同源策略及限制
- 前后端如何通信
- 如何创建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=true
return script
}
util.jsonp=function(url, onsuccess, onerror, charset){
// 告诉后端回调的名称
var callbackName=util.getName('tt_player')
// 在window注册一个全局callback
window[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").contentWindow
child.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接口,就可跨源通信