1. 窗口之间通信
1. document.domain
场景: 给不同源(但是两者的上级域名相同)的网页设置:
document.domain = '两者的上级域名';
如:image.baidu.com和video.baidu.com就可以通过这个方法。
则可以通过js读取彼此的Cookie, 对于iframe窗口可以获取彼此的DOM。
对于服务器通过Set-Cookie返回的Cookie, 可以使其domain属性等于其一级域名。
2. 片段识别符(url#后面的部分)
场景: iframe跨窗口通信。
示例: 父窗口给子窗口设置带#的url;子窗口通过监听hashchange事件,获取#数据。
// 父窗口
iframe = document.querySelector('iframe');
iframe.src = OriginalUrl + '#' + data;
// 子窗口
window.onhashchange = function(e) {
// data = window.location.hash
}
也可以通过子窗口修改父窗口的#部分
parent.location.href = OriginalUrl + '#' +data;
3.window.postMessage-H5
这是一个跨文档通信的API。
语法:
otherWindow.postMessage(message, targetOrigin[, transfer]); // otherWindow可以是其他窗口的索引,如iframe.contentWindow; window.opener等 // message是需要传递的数据 // targetOrigin是目标源,消息会发送给和这个同源的地址;不确定可以是'*'
然后在目标页面监听message事件
window.onmessage = function(e) {
// e.data
// e.origin 通过该属性过滤监听的数据
// e.source
}
2. AJAX通信
1. nginx
架设服务器代理,浏览器通过请求同源服务器,再由该服务器请求外部服务。
2. JSONP
特点: 只适用于GET方法。需要服务器端配合完成。
浏览器通过动态添加script标签(不受同源策略限制),向服务器请求JSON数据。
服务器收到请求后将数据放在指定名字的回调函数里返回回来。
客户端代码(部署在3000端口):
function jsonp({url, params, cb}) {
return new Promise((resolve,reject) => {
const script = document.createElement('script');
// 全局函数
window[cb] = function(data) {
resolve(data);
document.body.removeChild(script);//请求完成
}
let urlArr = [];
params = {...params, cb};
for(let key in params) {
urlArr.push(`${key}=${params[key]}`)
}
script.src = `${url}?${urlArr.join('&')}`;
document.body.appendChild(script); // 返回一个带参数的全局执行函数cb(data)
})
}
jsonp({
url: 'http://localhost:3001/query',
params: {a: 'b'}, //传参
cb: 'show' //指定回调函数名
}).then(data => {
console.log('data-->',data); //{name: 'lyra'}
})
服务器代码:
const express = require('express');
const app = express();
app.get('/query', (req, res) => {
const { a, cb } = req.query;
const data = {name: 'lyra'};
res.end(`${cb}(${JSON.stringify(data)})`); //相当于返回一个立即执行函数show({name: 'lyra'})
})
app.listen(3001)
3. WebSocket
WebSocket是一种通信协议,使用ws://(非安全)和wss://(安全)作为协议前缀。
特点:该协议不实行同源政策,只要服务器支持,就可以跨域通信。
客户端(部署在3000端口)示例:
const ws = new WebSocket('ws://localhost:3002');
ws.onopen = function() {
ws.send('to server')
}
ws.onmessage = function(e) {
console.log(e.data);
}
服务器端示例:
const express = require('express');
const app = express();
const WebSocket = require('ws'); // npm install ws
const socket = new WebSocket.Server({port: 3002}); //WebSocket单独一个端口
socket.on('connection', function(ws) {
ws.on('message', function(data) {
ws.send('hello,I am server')
})
})
app.get('/get', function(req,res) {
res.end('end')
})
app.listen(3001)
4. CORS(Cross-Origin Resource Sharing)
Ajax请求的根本解决办法,是W3C标准。允许任何类型的请求。需要浏览器和服务器同时支持。
主要是服务器支持。
上面的三种办法都有局限:JSONP只支持GET,WebSocket只支持ws://协议。