有一个理论,叫专家盲点,你问一个气象家,什么是风,他会一脸正经,一字一句的说:‘风是由空气流动引发的一种天然现象,它是由太阳辐射热引发的。。。’而后你就。。。若是回答的是:‘你感觉一下,这就是风’,你是否是会瞬间明白呢。若是你想检验你是否学懂了一个知识点,你能够这样检验,试着向一个小白解释这个知识点,,看看他能不能听懂。我就是想检验一下偶本身,,也许没人看,但,根本目的不是为了让别人看到,由于知识有输出,你就会有输入。。html
好比:你本身作了一个Web应用,功能是展现各地天气状况,好了,你的页面都已经写好了,但我改如何获取各地的天气状况呢,这就须要你经过请求去获取,好比你的天气数据来源是中国天气网,那么你就须要向该网站的天气API发送请求获取天气数据。可是,,人家的数据你是访问不到的,由于浏览器不会容许你的网站从第三方网站获取数据,这是由于浏览器的同源政策,所谓同源,指两个网站的协议,域名,端口号都相同,这样两个网站直接才能相互通讯。同源政策是网景公司引入浏览器的,如今浏览器都支持,目的是为了保证用户信息安全。
可是,安全是安全了,但咱们的功能该如何实现呢?即如何向第三方发起请求,两者进行通讯呢?这就是所谓的跨域。前端
如今咱们知道了,须要跨域才能进行两个非同源的网站的通讯,那具体该如何实现呢?有如下几种方法:chrome
JSONP原理: 利用script标签没有跨域限制的特性,让它指向第三方网站,即用script标签发出请求,但它请求的资源会被当成JS去执行,那如何让这个返回的数据可以被我所用,可以被获得执行呢?这就须要第三方网站给你的数据是一个数据JSON包,它返回的数据,不是简单的数据,而是用一个回调函数包装起来的,做为函数参数返回给你本身已经定义好的函数,这个函数的功能就是你对数据的操做处理。这样就能够请求到底三方的资源了,,但前提是须要第三方给你提供这个请求接口你才可以请求到数据。后端
前端代码跨域
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>news</title> <style> .container { width: 900px; margin: 0 auto; } </style> </head> <body> <div class="container"> <ul class="news"> <li>第11日前瞻:中国冲击4金 博尔特再战</li> <li>男双力争会师决赛 </li> <li>女排将死磕巴西!</li> </ul> <button class="change">换一组</button> </div> <script> $('.change').addEventListener('click', function() { var script = document.createElement('script'); //建立一个script标签 script.src = 'http://localhost:8080/getNews?callback=appendHtml'; document.head.appendChild(script); document.head.removeChild(script); }) function appendHtml(news) { var html = ''; for (var i = 0; i < news.length; i++) { html += '<li>' + news[i] + '</li>'; } console.log(html); $('.news').innerHTML = html; } function $(id) { return document.querySelector(id); } </script> </html>
后端数据mock浏览器
app.get('/getNews', function(req, res) { var news = [ "第11日前瞻:中国冲击4金 博尔特再战200米羽球", "正直播柴飚/洪炜出战 男双力争会师决赛", "女排将死磕巴西!郎平安排男陪练模仿对方核心", "没有中国选手和巨星的110米栏 咱们还看吗?", "中英上演奥运金牌大战", "博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多", "最“出柜”奥运?同性之爱闪耀里约", "下跪拜谢与洪荒之力同样 都是真情流露" ] var data = []; for (var i = 0; i < 3; i++) { var index = parseInt(Math.random() * news.length); data.push(news[index]); news.splice(index, 1); } var cb = req.query.callback; //获取请求参数 if (cb) { //判断是否有回调函数这个参数 res.send(cb + '(' + JSON.stringify(data) + ')'); //若是有:就会返回appendHtml() } else { res.send(data); } })
前端代码安全
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>news</title> <style> .container { width: 900px; margin: 0 auto; } </style> </head> <body> <div class="container"> <ul class="news"> <li>第11日前瞻:中国冲击4金 博尔特再战</li> <li>男双力争会师决赛 </li> <li>女排将死磕巴西!</li> </ul> <button class="change">换一组</button> </div> <script> //注意,AJAX跨域并不须要前端代码改变什么,就和正常AJAX代码同样写就能够。。即,,AJAX自己就是支持跨域,只是后端须要支持 $('.change').addEventListener('click', function() { var xhr = new XMLHttpRequest(); xhr.open('get', 'http://b.jrg.com:8080/getNews', true); xhr.send(); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { appendHtml(JSON.parse(xhr.responseText)) } } }) function appendHtml(news) { var html = ''; for (var i = 0; i < news.length; i++) { html += '<li>' + news[i] + '</li>'; } console.log(html); $('.news').innerHTML = html; } function $(id) { return document.querySelector(id); } </script> </html>
后端数据mock服务器
app.get('/getNews', function(req, res) { var news = [ "第11日前瞻:中国冲击4金 博尔特再战200米羽球", "正直播柴飚/洪炜出战 男双力争会师决赛", "女排将死磕巴西!郎平安排男陪练模仿对方核心", "没有中国选手和巨星的110米栏 咱们还看吗?", "中英上演奥运金牌大战", "博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多", "最“出柜”奥运?同性之爱闪耀里约", "下跪拜谢与洪荒之力同样 都是真情流露" ] var data = []; for (var i = 0; i < 3; i++) { var index = parseInt(Math.random() * news.length); data.push(news[index]); news.splice(index, 1); } res.header("Access-Control-Allow-Origin", "http://a.jrg.com:8080"); //服务端在响应投加上容许跨域请求的网站便可,只有它容许的才能够访问到 //res.header("Access-Control-Allow-Origin", "*"); *表示接收全部跨域请求 res.send(data); })
<html> <style> .ct { width: 910px; margin: auto; } .main { float: left; width: 450px; height: 300px; border: 1px solid #ccc; } .main input { margin: 20px; width: 200px; } .iframe { float: right; } iframe { width: 450px; height: 300px; border: 1px dashed #ccc; } </style> <div class="ct"> <h1>使用降域实现跨域</h1> <div class="main"> <input type="text" placeholder="http://a.jrg.com:8080/a.html"> </div> <iframe src="b.html" frameborder="0"></iframe> </div> <script> //URL: http://a.jrg.com:8080/a.html document.querySelector('.main input').addEventListener('input', function() { console.log(this.value); window.frames[0].document.querySelector('input').value = this.value; }) // document.domain = "jrg.com" 这是降域 </script> </html>
子窗口代码app
<html> <style> html, body { margin: 0; } input { margin: 20px; width: 200px; } </style> <input id="input" type="text" placeholder="http://b.jrg.com:8080/b.html"> <script> // URL: http://b.jrg.com:8080/b.html document.querySelector('#input').addEventListener('input', function() { window.parent.document.querySelector('input').value = this.value; }) // document.domain = 'jrg.com'; 这是降域处理 </script> </html>
<html> <style> .ct { width: 910px; margin: auto; } .main { float: left; width: 450px; height: 300px; border: 1px solid #ccc; } .main input { margin: 20px; width: 200px; } .iframe { float: right; } iframe { width: 450px; height: 300px; border: 1px dashed #ccc; } </style> <div class="ct"> <h1>使用postMessage实现跨域</h1> <div class="main"> <input type="text" placeholder="http://a.jrg.com:8080/a.html"> </div> <iframe src="http://localhost:8080/b.html" frameborder="0"></iframe> </div> <script> //URL: http://a.jrg.com:8080/a.html $('.main input').addEventListener('input', function() { console.log(this.value); window.frames[0].postMessage(this.value, '*'); }) window.addEventListener('message', function(e) { $('.main input').value = e.data console.log(e.data); }); function $(id) { return document.querySelector(id); } </script> </html>
子窗口dom
<html> <style> html, body { margin: 0; } input { margin: 20px; width: 200px; } </style> <input id="input" type="text" placeholder="http://b.jrg.com:8080/b.html"> <script> // URL: http://b.jrg.com:8080/b.html $('#input').addEventListener('input', function() { window.parent.postMessage(this.value, '*'); }) window.addEventListener('message', function(e) { $('#input').value = e.data console.log(e.data); }); function $(id) { return document.querySelector(id); } </script> </html>
先后端代码都须要在静态服务器上运行,我用的是Nojs下的srver-mock工具。