JS跨域總結(jié)
更新時(shí)間:2012年08月30日 12:03:15 作者:
JS跨域總結(jié),主要是解決js中跨域訪問的我問題
javascript跨域有兩種情況:
1、基于同一父域的子域之間,如:a.c.com和b.c.com
2、基于不同的父域之間,如:www.a.com和www.b.com
3、端口的不同,如:www.a.com:8080和www.a.com:8088
4、協(xié)議不同,如:http://www.a.com和https://www.a.com
對于情況3和4,需要通過后臺proxy來解決,具體方式如下:
a、在發(fā)起方的域下創(chuàng)建proxy程序
b、發(fā)起方的js調(diào)用本域下的proxy程序
c、proxy將請求發(fā)送給接收方并獲取相應(yīng)數(shù)據(jù)
d、proxy將獲得的數(shù)據(jù)返回給發(fā)起方的js
發(fā)起方頁面代碼如下:
<form id="form1" runat="server">
<div>
<input type="text" id="txtSrc" value="http://www.gzsums.edu.cn/webclass/html/html_design.html" style="width: 378px" />
<input id="btnProxy" type="button" value="通過Proxy獲取數(shù)據(jù)" onclick="GetDataFromProxy();" /><br />
<br />
<br />
</div>
<div id="divData"></div>
</form>
</body>
<script language="javascript" type="text/javascript">
function GetDataFromProxy() {
var src = document.getElementById('txtSrc').value;
var request = null;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = function() {
var ready = request.readyState;
var data = null;
{
if (ready == 4) {
data = request.responseText;
document.getElementById('divData').innerHTML = data;
}
else {
document.getElementById('divData').text = "Loading";
}
}
}
var url = "Proxy.ashx?src=" + escape(src);
request.open("get",url,false);
request.send(null);
}
</script>
發(fā)起方Proxy代碼如下:
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.IO;
using System.Net;
using System.Text;
namespace WebApplication1
{
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Proxy : IHttpHandler
{
const int BUFFER_SIZE = 8 * 1024;
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string src = context.Request["src"];
WebRequest wr = WebRequest.Create(src);
WebResponse wres = wr.GetResponse();
Encoding resEncoding = System.Text.Encoding.GetEncoding("gb2312");
StreamReader sr = new StreamReader(wres.GetResponseStream(), resEncoding);
string html = sr.ReadToEnd();
sr.Close();
wres.Close();
context.Response.Write("<br/><br/><br/><br/>");
context.Response.Write(html);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
而情況1和2除了通過后臺proxy這種方式外,還可以有7種辦法來解決:
1、document.domain+iframe(只能解決情況1):
a、在發(fā)起方頁面和接收方頁面設(shè)置document.domain,并將值設(shè)為父域的主域名(window.location.hostname)
b、在發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,iframe的源是接收方頁面
c、根據(jù)瀏覽器的不同,通過iframe.contentDocument || iframe.contentWindow.document來獲得接收方頁面的內(nèi)容
d、通過獲得的接收方頁面的內(nèi)容來與接收方進(jìn)行交互
這種方法有個(gè)缺點(diǎn),就是當(dāng)一個(gè)域被攻擊時(shí),另一個(gè)域會有安全漏洞出現(xiàn)。
發(fā)起方頁面代碼如下:
<body>
<div>
<input type="text" id="txtSrc" value="http://b.a.com/DomainTest2.htm" style="width: 378px" />
<input id="btnDomain" type="button" value="通過Domain獲取數(shù)據(jù)" onclick="GetDataFromDomain();" /><br />
<br />
<br />
</div>
<div id="divData"></div>
</body>
<script language="javascript" type="text/javascript">
document.domain = 'a.com';
var src = document.getElementById('txtSrc').value;
var ifr = document.createElement('iframe');
ifr.src = src;
ifr.style.display = 'none';
document.body.appendChild(ifr);
function GetDataFromDomain() {
var doc = ifr.contentDocument || ifr.contentWindow.document;
alert(doc.getElementById("data").value);
}
</script>
接收方頁面代碼如下:
<body>
<input type="hidden" id="data" value="Cross Domain" style="width: 378px" />
</body>
<script language="javascript" type="text/javascript">
document.domain = 'a.com';
</script>
2、動態(tài)創(chuàng)建script:
a、在發(fā)起方頁面動態(tài)加載一個(gè)script,script的URL指向接收方的一個(gè)處理地址(后臺),該地址返回的javascript方法會被執(zhí)行,另外URL中可以傳入一些參數(shù),該方法只支持GET方式提交參數(shù)。
b、加載的script可以在調(diào)用跨域js方法后再做一些自己的處理
發(fā)起方頁面的代碼如下:
<head>
<title>Script Test</title>
<script language="javascript" type="text/javascript">
function load_script(callback){
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
var src = document.getElementById('txtSrc').value;
script.type = 'text/javascript';
script.src = src;
//借鑒了jQuery的script跨域方法
script.onload = script.onreadystatechange = function(){
if((!this.readyState||this.readyState === "loaded"||this.readyState === "complete")){
callback && callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
head.insertBefore( script, head.firstChild );
}
</script>
</head>
<body>
<input type="text" id="txtSrc" value="http://www.b.com/scripttest.aspx" style="width: 378px" />
<input type="button" value="通過動態(tài)創(chuàng)建script標(biāo)簽來獲取數(shù)據(jù)" onclick="load_script(function(){alert('動態(tài)加載script標(biāo)簽成功')})"/>
</body>
接收方服務(wù)器端代碼如下:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "application/x-javascript";
Response.Write(String.Format(@"alert('{0}');", DateTime.Now));
Response.End();
}
3、location.hash+iframe:
a、發(fā)起方創(chuàng)建一個(gè)隱藏的iframe,iframe的源指向接收方的頁面,并通過接收方頁面的hash值來傳送數(shù)據(jù)
b、發(fā)起方創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并作相應(yīng)的處理
c、接收方創(chuàng)建一個(gè)隱藏的iframe,iframe的源指向發(fā)起方所在域的一個(gè)代理頁面,并將接收方根據(jù)發(fā)起方傳入的數(shù)據(jù)而處理后的數(shù)據(jù)通過代理頁面的hash值來傳送
d、接收方創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并作相應(yīng)的處理
e、代理頁面創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并同步更新發(fā)起方頁面的hash值
www.a.com/a.html#aaa,其中#aaa就是location.hash值
發(fā)起方頁面代碼如下:
<body>
<div>
<input type="text" id="txtSrc" value="1" style="width: 378px" />
<input id="btnAddHash" type="button" value="添加Hash值" onclick="addHash();" />
<iframe id="ifr1" style="display:none"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
function addHash() {
var src = document.getElementById('txtSrc').value;
if (src.length > 0) {
changeHash(src);
}
}
function changeHash(src) {
if (document.getElementById('ifr1')) {
var ifr = document.getElementById('ifr1');
ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;
}
else {
var ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr1');
ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
function checkHash() {
if (location.hash && location.hash.length > 1) {
changeHash(location.hash.substring(1));
}
}
setInterval(checkHash, 2000);
</script>
接收方頁面代碼如下:
<body>
<iframe id="ifr2" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
function checkHash() {
if (location.hash && location.hash.length > 1) {
var hashData = location.hash.substring(1);
var ifr = null;
if (document.getElementById('ifr2')) {
ifr = document.getElementById('ifr2');
}
else {
ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr2');
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
switch (hashData) {
case '1':
alert('One');
if (ifr) {
ifr.src = 'http://www.a.com/test/HashTest3.htm#2';
}
break;
case '2':
alert('Two');
if (ifr) {
ifr.src = 'http://www.a.com/test/HashTest3.htm#1';
}
break;
default:
break;
}
}
}
setInterval(checkHash, 2000);
</script>
發(fā)起方域下的代理頁面代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
function checkHash() {
if (parent && parent.parent && parent.parent.location && self.location.hash.length > 1) {
parent.parent.location.hash = self.location.hash.substring(1);
}
}
setInterval(checkHash, 500);
</script>
4、window.name:
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、接收方在自己頁面通過script將需要傳送的數(shù)據(jù)放入window.name里
c、發(fā)起方在iframe的onload方法里將iframe的源改為和自己在同一個(gè)域下的代理頁面(因?yàn)橹荒苁峭粋€(gè)域下才能訪問window.name的值)
d、獲取window.name的值(雖然iframe的源改變了,但是window.name的值不會變)
window.name的值差不多可以有2MB大小
發(fā)起方頁面代碼如下:
<body>
<div>
<input id="btnName" type="button" value="通過window.name獲取數(shù)據(jù)" onclick="getData();" />
<iframe id="ifr1" style="display:none" src="http://www.b.com/Test/NameTest2.htm"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
var ischanged = false;
function changeSrc() {
if (document.getElementById('ifr1')) {
var ifr = document.getElementById('ifr1');
if (!ischanged) {
ischanged = true;
ifr.contentWindow.location = 'http://www.a.com/Test/NameTest3.htm';
}
else {
var data = ifr.contentWindow.name;
alert(data);
}
}
else {
var ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr1');
ifr.src = 'http://www.b.com/Test/NameTest2.htm';
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
function getData() {
setInterval(changeSrc, 2000);
}
</script>
接收方頁面代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
window.name = 'NameTest2';
</script>
發(fā)起方域下的代理頁面代碼如下:
<body></body>
(其實(shí)什么都不用寫)
5、HTML5的postMessage
a、receiverWindow.postMessage(msg, targetOrigin),receiverWindow就是對接收消息的window的引用,可以是iframe的contentWindow/window.open的返回值/window.frames中的一個(gè);msg就是要發(fā)送的消息,string類型;targetOrigin用于限制receiverWindow的URI,包括主域名和端口,使用“*”表示無限制,但是為了安全起見還是需要設(shè)置下,以防把消息發(fā)送給惡意的網(wǎng)站,如果targetOrigin的URI和receiverWindow的不符,則放棄發(fā)送消息。
b、接收方通過message事件來獲得消息,并且通過event.origin的屬性來驗(yàn)證發(fā)送方并通過event.data來獲得傳送的消息內(nèi)容,event.source來獲得發(fā)送方的window對象
發(fā)起方頁面代碼如下:
<body>
<div>
<input id="btnPostMessage" type="button" value="通過PostMessage獲取數(shù)據(jù)" onclick="getData();" />
<iframe id="ifr" style="display:none" src="http://www.b.com/Test/PostMessageTest2.htm"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
function getData() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://www.b.com';
if (ifr.contentWindow.postMessage) {
ifr.contentWindow.postMessage('PostMessageTest2', targetOrigin);
}
}
</script>
接收方頁面代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
window.addEventListener('message', function(event) {
if (event.origin == 'http://www.a.com') {
alert(event.data);
alert(event.source);
}
}, false);
</script>
6、window.opener(適用于IE6、7,也就是operner hack方法,不過貌似現(xiàn)在已經(jīng)不管用了,只要打過微軟的安全補(bǔ)丁.kb2497640就不能用了)
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、發(fā)起方頁面通過iframe.contentWindow.opener = {a: function(params){...}, b: function(params){...} ...}來定義可被接收方調(diào)用的方法
c、接收方頁面通過window.opener.a/window.opener.b來調(diào)用發(fā)起方定義的方法
d、接收方頁面通過parent.opener = {c: function(params){...}, d: function(params){...} ...}來定義可被發(fā)起方調(diào)用的方法
e、發(fā)起方頁面通過opener.c/opener.d來調(diào)用接收方定義的方法
其實(shí)原理就是重置opener對象
發(fā)起方頁面代碼如下:
<body>
<iframe id="ifr" src="http://www.b.com/test/OpenerTest2.htm" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
var ifr = document.getElementById('ifr');
ifr.contentWindow.opener = { a: function(msg) { alert('我調(diào)用了a方法獲得了消息:' + msg); } }
</script>
接收方頁面代碼如下:
<body>
</body>
<script language="javascript" type="text/javascript">
window.opener.a('aaa');
</script>
7、window.navigator(適用于IE6、7,貌似現(xiàn)在還能用,還沒被補(bǔ)丁掉)
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、發(fā)起方頁面通過window.navigator.a = function(params){...}; window.navigator.b = function(params){...}; 來定義被接收方調(diào)用的方法
c、接收方頁面通過window.navigator.a(params); window.navigator.b(params);來調(diào)用發(fā)起方定義的方法
d、接收方頁面通過window.navigator.c = function(params){...}; window.navigator.d = function(params){...}; 來定義被發(fā)起方調(diào)用的方法
e、發(fā)起方頁面通過window.navigator.c(params); window.navigator.d(params);來調(diào)用接收方定義的方法
發(fā)起方頁面代碼如下:
<body>
<iframe id="ifr" src="http://www.b.com/test/NavigatorTest2.htm" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
window.navigator.a = function(msg) { alert('我調(diào)用了a方法獲得了消息:' + msg); }
window.navigator.b = function(msg) { alert('我調(diào)用了b方法獲得了消息:' + msg); }
setInterval(function() { window.navigator.c('ccc'); }, 2000);
setInterval(function() { window.navigator.d('ddd'); }, 2000);
</script>
接收方頁面代碼如下:
<body>
</body>
<script language="javascript" type="text/javascript">
window.navigator.c = function(msg) { alert('我調(diào)用了c方法獲得了消息:' + msg); }
window.navigator.d = function(msg) { alert('我調(diào)用了d方法獲得了消息:' + msg); }
setInterval(function() { window.navigator.a('aaa'); }, 2000);
setInterval(function() { window.navigator.b('bbb'); }, 2000);
</script>
1、基于同一父域的子域之間,如:a.c.com和b.c.com
2、基于不同的父域之間,如:www.a.com和www.b.com
3、端口的不同,如:www.a.com:8080和www.a.com:8088
4、協(xié)議不同,如:http://www.a.com和https://www.a.com
對于情況3和4,需要通過后臺proxy來解決,具體方式如下:
a、在發(fā)起方的域下創(chuàng)建proxy程序
b、發(fā)起方的js調(diào)用本域下的proxy程序
c、proxy將請求發(fā)送給接收方并獲取相應(yīng)數(shù)據(jù)
d、proxy將獲得的數(shù)據(jù)返回給發(fā)起方的js
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<form id="form1" runat="server">
<div>
<input type="text" id="txtSrc" value="http://www.gzsums.edu.cn/webclass/html/html_design.html" style="width: 378px" />
<input id="btnProxy" type="button" value="通過Proxy獲取數(shù)據(jù)" onclick="GetDataFromProxy();" /><br />
<br />
<br />
</div>
<div id="divData"></div>
</form>
</body>
<script language="javascript" type="text/javascript">
function GetDataFromProxy() {
var src = document.getElementById('txtSrc').value;
var request = null;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = function() {
var ready = request.readyState;
var data = null;
{
if (ready == 4) {
data = request.responseText;
document.getElementById('divData').innerHTML = data;
}
else {
document.getElementById('divData').text = "Loading";
}
}
}
var url = "Proxy.ashx?src=" + escape(src);
request.open("get",url,false);
request.send(null);
}
</script>
發(fā)起方Proxy代碼如下:
復(fù)制代碼 代碼如下:
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.IO;
using System.Net;
using System.Text;
namespace WebApplication1
{
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Proxy : IHttpHandler
{
const int BUFFER_SIZE = 8 * 1024;
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string src = context.Request["src"];
WebRequest wr = WebRequest.Create(src);
WebResponse wres = wr.GetResponse();
Encoding resEncoding = System.Text.Encoding.GetEncoding("gb2312");
StreamReader sr = new StreamReader(wres.GetResponseStream(), resEncoding);
string html = sr.ReadToEnd();
sr.Close();
wres.Close();
context.Response.Write("<br/><br/><br/><br/>");
context.Response.Write(html);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
而情況1和2除了通過后臺proxy這種方式外,還可以有7種辦法來解決:
1、document.domain+iframe(只能解決情況1):
a、在發(fā)起方頁面和接收方頁面設(shè)置document.domain,并將值設(shè)為父域的主域名(window.location.hostname)
b、在發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,iframe的源是接收方頁面
c、根據(jù)瀏覽器的不同,通過iframe.contentDocument || iframe.contentWindow.document來獲得接收方頁面的內(nèi)容
d、通過獲得的接收方頁面的內(nèi)容來與接收方進(jìn)行交互
這種方法有個(gè)缺點(diǎn),就是當(dāng)一個(gè)域被攻擊時(shí),另一個(gè)域會有安全漏洞出現(xiàn)。
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<div>
<input type="text" id="txtSrc" value="http://b.a.com/DomainTest2.htm" style="width: 378px" />
<input id="btnDomain" type="button" value="通過Domain獲取數(shù)據(jù)" onclick="GetDataFromDomain();" /><br />
<br />
<br />
</div>
<div id="divData"></div>
</body>
<script language="javascript" type="text/javascript">
document.domain = 'a.com';
var src = document.getElementById('txtSrc').value;
var ifr = document.createElement('iframe');
ifr.src = src;
ifr.style.display = 'none';
document.body.appendChild(ifr);
function GetDataFromDomain() {
var doc = ifr.contentDocument || ifr.contentWindow.document;
alert(doc.getElementById("data").value);
}
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<input type="hidden" id="data" value="Cross Domain" style="width: 378px" />
</body>
<script language="javascript" type="text/javascript">
document.domain = 'a.com';
</script>
2、動態(tài)創(chuàng)建script:
a、在發(fā)起方頁面動態(tài)加載一個(gè)script,script的URL指向接收方的一個(gè)處理地址(后臺),該地址返回的javascript方法會被執(zhí)行,另外URL中可以傳入一些參數(shù),該方法只支持GET方式提交參數(shù)。
b、加載的script可以在調(diào)用跨域js方法后再做一些自己的處理
發(fā)起方頁面的代碼如下:
復(fù)制代碼 代碼如下:
<head>
<title>Script Test</title>
<script language="javascript" type="text/javascript">
function load_script(callback){
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
var src = document.getElementById('txtSrc').value;
script.type = 'text/javascript';
script.src = src;
//借鑒了jQuery的script跨域方法
script.onload = script.onreadystatechange = function(){
if((!this.readyState||this.readyState === "loaded"||this.readyState === "complete")){
callback && callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
head.insertBefore( script, head.firstChild );
}
</script>
</head>
<body>
<input type="text" id="txtSrc" value="http://www.b.com/scripttest.aspx" style="width: 378px" />
<input type="button" value="通過動態(tài)創(chuàng)建script標(biāo)簽來獲取數(shù)據(jù)" onclick="load_script(function(){alert('動態(tài)加載script標(biāo)簽成功')})"/>
</body>
接收方服務(wù)器端代碼如下:
復(fù)制代碼 代碼如下:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "application/x-javascript";
Response.Write(String.Format(@"alert('{0}');", DateTime.Now));
Response.End();
}
3、location.hash+iframe:
a、發(fā)起方創(chuàng)建一個(gè)隱藏的iframe,iframe的源指向接收方的頁面,并通過接收方頁面的hash值來傳送數(shù)據(jù)
b、發(fā)起方創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并作相應(yīng)的處理
c、接收方創(chuàng)建一個(gè)隱藏的iframe,iframe的源指向發(fā)起方所在域的一個(gè)代理頁面,并將接收方根據(jù)發(fā)起方傳入的數(shù)據(jù)而處理后的數(shù)據(jù)通過代理頁面的hash值來傳送
d、接收方創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并作相應(yīng)的處理
e、代理頁面創(chuàng)建一個(gè)定時(shí)器,定時(shí)檢查自己的location.hash并同步更新發(fā)起方頁面的hash值
www.a.com/a.html#aaa,其中#aaa就是location.hash值
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<div>
<input type="text" id="txtSrc" value="1" style="width: 378px" />
<input id="btnAddHash" type="button" value="添加Hash值" onclick="addHash();" />
<iframe id="ifr1" style="display:none"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
function addHash() {
var src = document.getElementById('txtSrc').value;
if (src.length > 0) {
changeHash(src);
}
}
function changeHash(src) {
if (document.getElementById('ifr1')) {
var ifr = document.getElementById('ifr1');
ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;
}
else {
var ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr1');
ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
function checkHash() {
if (location.hash && location.hash.length > 1) {
changeHash(location.hash.substring(1));
}
}
setInterval(checkHash, 2000);
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<iframe id="ifr2" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
function checkHash() {
if (location.hash && location.hash.length > 1) {
var hashData = location.hash.substring(1);
var ifr = null;
if (document.getElementById('ifr2')) {
ifr = document.getElementById('ifr2');
}
else {
ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr2');
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
switch (hashData) {
case '1':
alert('One');
if (ifr) {
ifr.src = 'http://www.a.com/test/HashTest3.htm#2';
}
break;
case '2':
alert('Two');
if (ifr) {
ifr.src = 'http://www.a.com/test/HashTest3.htm#1';
}
break;
default:
break;
}
}
}
setInterval(checkHash, 2000);
</script>
發(fā)起方域下的代理頁面代碼如下:
復(fù)制代碼 代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
function checkHash() {
if (parent && parent.parent && parent.parent.location && self.location.hash.length > 1) {
parent.parent.location.hash = self.location.hash.substring(1);
}
}
setInterval(checkHash, 500);
</script>
4、window.name:
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、接收方在自己頁面通過script將需要傳送的數(shù)據(jù)放入window.name里
c、發(fā)起方在iframe的onload方法里將iframe的源改為和自己在同一個(gè)域下的代理頁面(因?yàn)橹荒苁峭粋€(gè)域下才能訪問window.name的值)
d、獲取window.name的值(雖然iframe的源改變了,但是window.name的值不會變)
window.name的值差不多可以有2MB大小
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<div>
<input id="btnName" type="button" value="通過window.name獲取數(shù)據(jù)" onclick="getData();" />
<iframe id="ifr1" style="display:none" src="http://www.b.com/Test/NameTest2.htm"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
var ischanged = false;
function changeSrc() {
if (document.getElementById('ifr1')) {
var ifr = document.getElementById('ifr1');
if (!ischanged) {
ischanged = true;
ifr.contentWindow.location = 'http://www.a.com/Test/NameTest3.htm';
}
else {
var data = ifr.contentWindow.name;
alert(data);
}
}
else {
var ifr = document.createElement('iframe');
ifr.setAttribute('id', 'ifr1');
ifr.src = 'http://www.b.com/Test/NameTest2.htm';
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
function getData() {
setInterval(changeSrc, 2000);
}
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
window.name = 'NameTest2';
</script>
發(fā)起方域下的代理頁面代碼如下:
<body></body>
(其實(shí)什么都不用寫)
5、HTML5的postMessage
a、receiverWindow.postMessage(msg, targetOrigin),receiverWindow就是對接收消息的window的引用,可以是iframe的contentWindow/window.open的返回值/window.frames中的一個(gè);msg就是要發(fā)送的消息,string類型;targetOrigin用于限制receiverWindow的URI,包括主域名和端口,使用“*”表示無限制,但是為了安全起見還是需要設(shè)置下,以防把消息發(fā)送給惡意的網(wǎng)站,如果targetOrigin的URI和receiverWindow的不符,則放棄發(fā)送消息。
b、接收方通過message事件來獲得消息,并且通過event.origin的屬性來驗(yàn)證發(fā)送方并通過event.data來獲得傳送的消息內(nèi)容,event.source來獲得發(fā)送方的window對象
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<div>
<input id="btnPostMessage" type="button" value="通過PostMessage獲取數(shù)據(jù)" onclick="getData();" />
<iframe id="ifr" style="display:none" src="http://www.b.com/Test/PostMessageTest2.htm"></iframe>
</div>
</body>
<script language="javascript" type="text/javascript">
function getData() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://www.b.com';
if (ifr.contentWindow.postMessage) {
ifr.contentWindow.postMessage('PostMessageTest2', targetOrigin);
}
}
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body></body>
<script language="javascript" type="text/javascript">
window.addEventListener('message', function(event) {
if (event.origin == 'http://www.a.com') {
alert(event.data);
alert(event.source);
}
}, false);
</script>
6、window.opener(適用于IE6、7,也就是operner hack方法,不過貌似現(xiàn)在已經(jīng)不管用了,只要打過微軟的安全補(bǔ)丁.kb2497640就不能用了)
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、發(fā)起方頁面通過iframe.contentWindow.opener = {a: function(params){...}, b: function(params){...} ...}來定義可被接收方調(diào)用的方法
c、接收方頁面通過window.opener.a/window.opener.b來調(diào)用發(fā)起方定義的方法
d、接收方頁面通過parent.opener = {c: function(params){...}, d: function(params){...} ...}來定義可被發(fā)起方調(diào)用的方法
e、發(fā)起方頁面通過opener.c/opener.d來調(diào)用接收方定義的方法
其實(shí)原理就是重置opener對象
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<iframe id="ifr" src="http://www.b.com/test/OpenerTest2.htm" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
var ifr = document.getElementById('ifr');
ifr.contentWindow.opener = { a: function(msg) { alert('我調(diào)用了a方法獲得了消息:' + msg); } }
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
</body>
<script language="javascript" type="text/javascript">
window.opener.a('aaa');
</script>
7、window.navigator(適用于IE6、7,貌似現(xiàn)在還能用,還沒被補(bǔ)丁掉)
a、發(fā)起方頁面創(chuàng)建一個(gè)隱藏的iframe,并且源指向接收方頁面
b、發(fā)起方頁面通過window.navigator.a = function(params){...}; window.navigator.b = function(params){...}; 來定義被接收方調(diào)用的方法
c、接收方頁面通過window.navigator.a(params); window.navigator.b(params);來調(diào)用發(fā)起方定義的方法
d、接收方頁面通過window.navigator.c = function(params){...}; window.navigator.d = function(params){...}; 來定義被發(fā)起方調(diào)用的方法
e、發(fā)起方頁面通過window.navigator.c(params); window.navigator.d(params);來調(diào)用接收方定義的方法
發(fā)起方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
<iframe id="ifr" src="http://www.b.com/test/NavigatorTest2.htm" style="display:none"></iframe>
</body>
<script language="javascript" type="text/javascript">
window.navigator.a = function(msg) { alert('我調(diào)用了a方法獲得了消息:' + msg); }
window.navigator.b = function(msg) { alert('我調(diào)用了b方法獲得了消息:' + msg); }
setInterval(function() { window.navigator.c('ccc'); }, 2000);
setInterval(function() { window.navigator.d('ddd'); }, 2000);
</script>
接收方頁面代碼如下:
復(fù)制代碼 代碼如下:
<body>
</body>
<script language="javascript" type="text/javascript">
window.navigator.c = function(msg) { alert('我調(diào)用了c方法獲得了消息:' + msg); }
window.navigator.d = function(msg) { alert('我調(diào)用了d方法獲得了消息:' + msg); }
setInterval(function() { window.navigator.a('aaa'); }, 2000);
setInterval(function() { window.navigator.b('bbb'); }, 2000);
</script>
相關(guān)文章
requirejs按需加載angularjs文件實(shí)例
本篇文章主要介紹了requirejs按需加載angularjs文件實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06
uniapp項(xiàng)目使用防抖及節(jié)流的方案實(shí)戰(zhàn)
防抖就是指觸發(fā)事件后把觸發(fā)非常頻繁的事件合并成一次去執(zhí)行,節(jié)流是指頻繁觸發(fā)事件時(shí)只會在指定的時(shí)間段內(nèi)執(zhí)行事件回調(diào),即觸發(fā)事件間隔大于等于指定的時(shí)間才會執(zhí)行回調(diào)函數(shù),這篇文章主要給大家介紹了關(guān)于uniapp項(xiàng)目使用防抖及節(jié)流的相關(guān)資料,需要的朋友可以參考下2023-01-01
一個(gè)js封裝的不錯(cuò)的選項(xiàng)卡效果代碼
在論壇里經(jīng)??吹饺藛栠x項(xiàng)卡或者類似選項(xiàng)卡的切換效果 這里封裝了個(gè)js,希望對大家有用 所有代碼都在下面了 如果有錯(cuò)誤或者建議,可以回貼告訴我,謝謝2008-02-02
JavaScript Promise原理與實(shí)現(xiàn)刨析
首先呢,Promise是異步中比較重要的知識點(diǎn),學(xué)習(xí)的最好方法就是掌握它的基本原理。所以這一篇主要說一下如何用JS來實(shí)現(xiàn)一個(gè)自己的promise2022-10-10
js 實(shí)現(xiàn) input type="file" 文件上傳示例代碼
在開發(fā)中,文件上傳必不可少但是它長得又丑、瀏覽的字樣不能換,一般會讓其隱藏點(diǎn)其他的標(biāo)簽(圖片等)來時(shí)實(shí)現(xiàn)選擇文件上傳功能2013-08-08
使用DeviceOne實(shí)現(xiàn)微信小程序功能
本文主要對小程序的優(yōu)缺點(diǎn)和DeviceOne的特點(diǎn)進(jìn)行介紹,分享了使用DeviceOne實(shí)現(xiàn)微信小程序功能的實(shí)例代碼,具有一定的參考價(jià)值。下面跟著小編一起來看下吧2016-12-12
javascript createAdder函數(shù)功能與使用說明
createAdder(x)是一個(gè)函數(shù),返回一個(gè)函數(shù)。在JavaScript中,函數(shù)是第一類對象:另外它們可以被傳遞到其他函數(shù)作為參數(shù)和函數(shù)返回。在這種情況下,函數(shù)返回本身就是一個(gè)函數(shù)接受一個(gè)參數(shù),并增加了一些東西。2010-06-06

