JSONP
jsonp的原理就是利用<script>标签没有跨域限制,通过<script>标签src属性,将本地的全局函数通过callback传到服务器,服务端将接口返回数据拼凑到callback函数中,返回给客服端
实现思路
服务端的代码:
let express = require('express');
app = express();
app.listen('8001', () => {
console.log('ok');
})
app.get('/list', (req,res) => {
let { callback } = req.query;
let data = {
code: 0,
message:'发送的数据'
}
res.send(`${callback}(${JSON.stringify(data)}`)
})
客户端代码
<script>
let script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
jsonp的缺点:只能发送get一种请求。安全性低
CORS 跨域资源共享
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
客服端:发送请求
服务端通过配置一些头信息 Access-Control-Allow-Origin:必选
所有的cors请求都会预先发一个options请求 发送真正请求前先发一个试探性请求
缺点是允许源只能写一个地址 或者直接写* 写*不安全并且不允许携带cookie了
nginx反向代理
不需要前端处理
http proxy
webpack 配置 webpack-dev-server配置 (node启了一个本地服务器)
devServer:{
port:3000,
progress:true,
contentBase:'./bulid',
proxy:{
'/':{ 以/ 开头的路径都转到target路径下
traget:'http://127.0.0.1:3001',
changeOrigin:true
}
}
}
Window.postMessage
实现跨源通信,两个不同页面的脚本实现通信
A页面
<body>
<iframe id="iframe" style="display:none" src="http://127.0.0.1:1002/MESSAGE/b.html"></iframe>
<script>
iframe.onload=function(){
iframe.contentWindow.postMessage('发送的数据','http://127.0.0.1:1002')
}
// 监听b页面传过来的数据
window.onmessage = function(ev){
console.log(ev.data)
}
</script>
</body>
B页面
<script>
//=> 监听A发送过来的信息
window.onmessage = function(ev){
console.log(ev.data)
//=>ev.source:A
ev.source.postMessage(ev.data+'@@@',ev.origin)
}
</script>
WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯
如果想完全搭建一个 WebSocket 服务端比较麻烦,又浪费时间。所以一般会使用Socket.io 这个库,
简单实现一个聊天功能:
服务端:
let express = require('express');
let app = express();
let server = require('http').createServer(app);
let io = require('socket.io')(server);
let path = require('path');
app.use('/', (req, res, next) => {
res.status(200).sendFile(path.resolve(__dirname, 'index.html'));
});
// 开启 socket.io
io.on('connection', (client) => {
// 如果有新客户端进来,显示 ID
console.log(`客户端 ID:${client.id}`);
// 监听客户端的输入信息
client.on('channel', (data) => {
console.log(`客户端 ${client.id} 发送信息 ${data}`);
io.emit('broadcast', data);
});
// 判断客户端是否关闭
client.on('disconnect', () => {
console.log(`客户端关闭:${client.id}`);
});
});
server.listen(3000, () => {
console.log('服务监听 3000 端口');
});
客户端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Socket.io</title>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.slim.js"></script>
</head>
<body>
<input type="text" id="input">
<button id="btn">send</button>
<div id="content-wrap"></div>
<script>
window.onload = function () {
let inputValue = null;
// 连接 socket.io
let socket = io('http://localhost:3000');
// 将创建的信息以添加 p 标签的形式展示成列表
socket.on('broadcast', data => {
let content = document.createElement('p');
content.innerHTML = data;
document.querySelector('#content-wrap').appendChild(content);
})
// 设置输入框的内容
let inputChangeHandle = (ev) => {
inputValue = ev.target.value;
}
// 获取输入框并监听输入
let inputDom = document.querySelector("#input");
inputDom.addEventListener('input', inputChangeHandle, false);
// 当用户点击发送信息的时候,进行数据交互
let sendHandle = () => {
socket.emit('channel', inputValue);
}
let btnDom = document.querySelector("#btn");
btnDom.addEventListener('click', sendHandle, false);
// 打页面卸载的时候,通知服务器关闭
window.onunload = () => {
btnDom.removeEventListener('click', sendHandle, false);
inputDom.removeEventListener('input', inputChangeHandle, false);
}
};
</script>
</body>
</html>
用on监听,用emit发送一个指令。