JS實(shí)現(xiàn)兩個(gè)跨域頁(yè)面實(shí)現(xiàn)量子糾纏互動(dòng)效果
本文約定:
A頁(yè)面:假設(shè)為a.com
B頁(yè)面:假設(shè)為b.com
一、同域頁(yè)面實(shí)現(xiàn)量子糾纏的一般方案

最近前端圈的量子糾纏交互動(dòng)效爆火,相信大家都了解了其中的實(shí)現(xiàn)原理,這里我再簡(jiǎn)單的介紹下,不了解的同學(xué)的可以學(xué)習(xí)一波。
原理就是,通過(guò)監(jiān)聽窗口的位置、大小等信息,然后實(shí)時(shí)地保存到localStorage中,另一個(gè)頁(yè)面通過(guò)監(jiān)聽strorage的改變,進(jìn)而動(dòng)態(tài)地改變頁(yè)面上物體的位置和顯示效果。
示例代碼如下:
// 將當(dāng)前頁(yè)面的中心位置坐標(biāo)保存到localStorage中
const savePageInfo = () => {
const centerX = window.innerWidth / 2 + window.screenLeft;
const centerY = window.innerHeight / 2 + window.screenTop;
const data = { centerX, centerY };
window.localStorage.setItem(pageId, JSON.stringify(data));
};
// localStorage被修改后的回調(diào)
const onStorage = (e) => {
console.log("otherPageInfo", JSON.parse(e.newValue));
}
const onReady = () => {
savePageInfo();
window.addEventListener("resize", savePageInfo);
window.addEventListener("storage", onStorage);
}
window.addEventListener("ready", onReady);
在這個(gè)案例中,由于兩個(gè)頁(yè)面是相同域下的,所以另外一個(gè)頁(yè)面可以通過(guò)監(jiān)聽strorage的改變,獲取到前一個(gè)頁(yè)面保存進(jìn)去的值,然后進(jìn)行交互,這里不得不佩服作者的奇思妙想。
那么問(wèn)題來(lái)了,如果兩個(gè)頁(yè)面是跨域的,單獨(dú)打開的兩個(gè)頁(yè)面又如何進(jìn)行實(shí)時(shí)地通信呢?有同學(xué)會(huì)說(shuō)用WebSocket,呃...,是可以實(shí)現(xiàn),但我們討論的是純前端的實(shí)現(xiàn),借助后端就沒(méi)啥意思了。
二、跨域頁(yè)面實(shí)現(xiàn)量子糾纏的終極方案
兩個(gè)跨域頁(yè)面想要通信就必須使用可以進(jìn)行跨域通信的API,大家肯定都想到了,對(duì),使用window.postMessage,但是A頁(yè)面要給B頁(yè)面發(fā)送消息,那么postMessage的window對(duì)象就必須是B頁(yè)面的window對(duì)象,而A和B兩個(gè)頁(yè)面是在兩個(gè)單獨(dú)的瀏覽器窗口中分別打開的,A頁(yè)面如何獲取到B頁(yè)面的window對(duì)象呢?
直接說(shuō)結(jié)論,終極方案就是,在A頁(yè)面中通過(guò)Iframe嵌入display為none的B頁(yè)面,A頁(yè)面監(jiān)聽窗口的位置、大小的改變,然后將窗口信息通過(guò)postMessage發(fā)送消息給B頁(yè)面,剛才說(shuō)了要給B頁(yè)面發(fā)送消息就必須拿到B頁(yè)面的window對(duì)象,那么如何拿到呢,就是通過(guò)Iframe.contentWindow,B頁(yè)面通過(guò)監(jiān)聽A頁(yè)面發(fā)送的message拿到信息,然后保存到window.localStorage中。這里有同學(xué)會(huì)好奇了,既然B頁(yè)面拿到了信息,為啥還要保存到localStorage中,為啥不直接使用呢?你聽我狡辯...,啊不,你聽我說(shuō),這里拿到信息的B頁(yè)面只是A頁(yè)面中嵌入的B頁(yè)面,不是用戶打開的另一個(gè)窗口中的B頁(yè)面,所以這時(shí)剩下的工作就是將嵌入的B頁(yè)面中的信息發(fā)送給另一個(gè)窗口的B頁(yè)面,就大功告成了。兩個(gè)都是B頁(yè)面,就不存在跨域啦,就使用上面那個(gè)方案,通過(guò)監(jiān)聽strorage的改變獲取就行了。
示例代碼如下:
A頁(yè)面
const postInfo = () => {
const bIframe = document.getElementById("bIframe");
if (bIframe) {
const centerX = window.innerWidth / 2 + window.screenLeft;
const centerY = window.innerHeight / 2 + window.screenTop;
const data = { centerX, centerY };
bIframe.contentWindow?.postMessage(
JSON.stringify(data),
"http://b.com"
);
}
};
const onMessage = (e) => {
if (e.origin !== "http://b.com") return;
if (e.data) {
window.localStorage.setItem("bPageInfo", e.data);
}
};
const onStorage = (e) => {
if (e.key === "bPageInfo") {
console.log("bPageInfo", JSON.parse(e.newValue));
}
};
const onReady = () => {
window.addEventListener("message", onMessage, false);
if (window.self === window.top) {
window.addEventListener("storage", onStorage);
window.addEventListener("resize", postInfo);
}
postInfo();
}
window.addEventListener("ready", onReady);
在A頁(yè)面中嵌入B頁(yè)面
<iframe
id="bIframe"
src="http://b.com"
style="display: none"
/>
B頁(yè)面
const postInfo = () => {
const aIframe = document.getElementById("aIframe");
if (aIframe) {
const centerX = window.innerWidth / 2 + window.screenLeft;
const centerY = window.innerHeight / 2 + window.screenTop;
const data = { centerX, centerY };
aIframe.contentWindow?.postMessage(
JSON.stringify(data),
"http://a.com"
);
}
};
const onMessage = (e) => {
if (e.origin !== "http://a.com") return;
if (e.data) {
window.localStorage.setItem("aPageInfo", e.data);
}
};
const onStorage = (e) => {
if (e.key === "aPageInfo") {
console.log("aPageInfo", JSON.parse(e.newValue));
}
};
const onReady = () => {
window.addEventListener("message", onMessage, false);
if (window.self === window.top) {
window.addEventListener("storage", onStorage);
window.addEventListener("resize", postInfo);
}
postInfo();
}
window.addEventListener("ready", onReady);
三、實(shí)戰(zhàn)案例

Visualization Collection網(wǎng)站中已經(jīng)實(shí)現(xiàn)了量子糾纏的效果,大家可以去玩一玩,該網(wǎng)站中的量子糾纏效果作為隱藏款案例,點(diǎn)擊網(wǎng)站左上角頭部的文字,即可觸發(fā),一般我不說(shuō)的。
體驗(yàn)地址(PC端):hepengwei.cn
源碼地址:github.com/hepengwei/visualization-collection
四、美中不足
大家也看到了,上面GIF圖中演示的還是同域頁(yè)面實(shí)現(xiàn)量子糾纏的效果,這里非常遺憾地告訴大家,跨域頁(yè)面實(shí)現(xiàn)量子糾纏只能在本地運(yùn)行的情況下才可實(shí)現(xiàn),部署到線上就不行了,監(jiān)聽storage的回調(diào)不會(huì)執(zhí)行,后面我也試過(guò)各種辦法,比如在定時(shí)器里循環(huán)去獲取localStorage中的值,使用Service Worker等均無(wú)法實(shí)現(xiàn),這應(yīng)該是瀏覽器為了安全考慮進(jìn)行了限制。
如果有想要看兩個(gè)跨域頁(yè)面在本地實(shí)現(xiàn)量子糾纏效果的同學(xué),可以自行到我GitHub上下載visualization-collection和michelle-design這兩個(gè)項(xiàng)目代碼,然后在本地運(yùn)行,就可以看到效果啦。
五、結(jié)語(yǔ)
該終極方案與我的另一篇文章《兩個(gè)跨越頁(yè)面進(jìn)行跳轉(zhuǎn)傳參的終極方案》中的終極方案有異曲同工之妙,都是通過(guò)在原先的頁(yè)面中無(wú)痕嵌入另一個(gè)頁(yè)面,然后通過(guò)myIframe.contentWindow.postMessage來(lái)發(fā)送消息,如此實(shí)現(xiàn)跨域信息的傳遞。兩個(gè)不同窗口打開的同域頁(yè)面,則通過(guò)將信息保存到localStorage,另一頁(yè)面通過(guò)監(jiān)聽storage改變的方式傳遞信息。
到此這篇關(guān)于JS實(shí)現(xiàn)兩個(gè)跨域頁(yè)面實(shí)現(xiàn)量子糾纏互動(dòng)效果的文章就介紹到這了,更多相關(guān)JS跨域頁(yè)面互動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Vconsole和Fillder進(jìn)行移動(dòng)端抓包調(diào)試方法
這篇文章主要介紹了利用Vconsole和Fillder進(jìn)行移動(dòng)端抓包調(diào)試,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03
JavaScript數(shù)據(jù)結(jié)構(gòu)與算法之隊(duì)列原理與用法實(shí)例詳解
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)與算法之隊(duì)列原理與用法,較為詳細(xì)的說(shuō)明了隊(duì)列的概念、原理,并結(jié)合實(shí)例形式分析了javascript實(shí)現(xiàn)與使用隊(duì)列的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2017-11-11
JavaScript利用正則表達(dá)式替換字符串中的內(nèi)容
本文主要介紹了JavaScript利用正則表達(dá)式替換字符串中內(nèi)容的具體實(shí)現(xiàn)方法,并做了簡(jiǎn)要注釋,便于理解。具有一定的參考價(jià)值,需要的朋友可以看下2016-12-12
網(wǎng)頁(yè)右側(cè)懸浮滾動(dòng)在線qq客服代碼示例
這篇文章主要介紹了網(wǎng)頁(yè)右側(cè)懸浮滾動(dòng)qq在線客服代碼示例,需要的朋友可以參考下2014-04-04
javascript的解析執(zhí)行順序在各個(gè)瀏覽器中的不同
javascript是一種解釋型語(yǔ)言,它的執(zhí)行是自上而下的。由于各個(gè)瀏覽器對(duì)它的理解有所差異,所以我們有必要深入理解js的執(zhí)行順序2014-03-03
JS實(shí)現(xiàn)在線統(tǒng)計(jì)一個(gè)頁(yè)面內(nèi)鼠標(biāo)點(diǎn)擊次數(shù)的方法
這篇文章主要介紹了JS實(shí)現(xiàn)在線統(tǒng)計(jì)一個(gè)頁(yè)面內(nèi)鼠標(biāo)點(diǎn)擊次數(shù)的方法,實(shí)例分析了javascript操作Cookie實(shí)現(xiàn)計(jì)數(shù)的技巧,需要的朋友可以參考下2015-02-02
僅IE9/10同時(shí)支持script元素的onload和onreadystatechange事件分析
測(cè)試結(jié)果可以看出,IE9后已經(jīng)開始支持script的onload事件了。一直以來(lái)我們判斷js文件是否已經(jīng)加載完成就是用以上的兩個(gè)事件。2011-04-04

