JS實現兩個跨域頁面實現量子糾纏互動效果
本文約定:
A頁面:假設為a.com
B頁面:假設為b.com
一、同域頁面實現量子糾纏的一般方案

最近前端圈的量子糾纏交互動效爆火,相信大家都了解了其中的實現原理,這里我再簡單的介紹下,不了解的同學的可以學習一波。
原理就是,通過監(jiān)聽窗口的位置、大小等信息,然后實時地保存到localStorage中,另一個頁面通過監(jiān)聽strorage的改變,進而動態(tài)地改變頁面上物體的位置和顯示效果。
示例代碼如下:
// 將當前頁面的中心位置坐標保存到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被修改后的回調
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);
在這個案例中,由于兩個頁面是相同域下的,所以另外一個頁面可以通過監(jiān)聽strorage的改變,獲取到前一個頁面保存進去的值,然后進行交互,這里不得不佩服作者的奇思妙想。
那么問題來了,如果兩個頁面是跨域的,單獨打開的兩個頁面又如何進行實時地通信呢?有同學會說用WebSocket,呃...,是可以實現,但我們討論的是純前端的實現,借助后端就沒啥意思了。
二、跨域頁面實現量子糾纏的終極方案
兩個跨域頁面想要通信就必須使用可以進行跨域通信的API,大家肯定都想到了,對,使用window.postMessage,但是A頁面要給B頁面發(fā)送消息,那么postMessage的window對象就必須是B頁面的window對象,而A和B兩個頁面是在兩個單獨的瀏覽器窗口中分別打開的,A頁面如何獲取到B頁面的window對象呢?
直接說結論,終極方案就是,在A頁面中通過Iframe嵌入display為none的B頁面,A頁面監(jiān)聽窗口的位置、大小的改變,然后將窗口信息通過postMessage發(fā)送消息給B頁面,剛才說了要給B頁面發(fā)送消息就必須拿到B頁面的window對象,那么如何拿到呢,就是通過Iframe.contentWindow,B頁面通過監(jiān)聽A頁面發(fā)送的message拿到信息,然后保存到window.localStorage中。這里有同學會好奇了,既然B頁面拿到了信息,為啥還要保存到localStorage中,為啥不直接使用呢?你聽我狡辯...,啊不,你聽我說,這里拿到信息的B頁面只是A頁面中嵌入的B頁面,不是用戶打開的另一個窗口中的B頁面,所以這時剩下的工作就是將嵌入的B頁面中的信息發(fā)送給另一個窗口的B頁面,就大功告成了。兩個都是B頁面,就不存在跨域啦,就使用上面那個方案,通過監(jiān)聽strorage的改變獲取就行了。
示例代碼如下:
A頁面
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頁面中嵌入B頁面
<iframe
id="bIframe"
src="http://b.com"
style="display: none"
/>
B頁面
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);
三、實戰(zhàn)案例

Visualization Collection網站中已經實現了量子糾纏的效果,大家可以去玩一玩,該網站中的量子糾纏效果作為隱藏款案例,點擊網站左上角頭部的文字,即可觸發(fā),一般我不說的。
體驗地址(PC端):hepengwei.cn
源碼地址:github.com/hepengwei/visualization-collection
四、美中不足
大家也看到了,上面GIF圖中演示的還是同域頁面實現量子糾纏的效果,這里非常遺憾地告訴大家,跨域頁面實現量子糾纏只能在本地運行的情況下才可實現,部署到線上就不行了,監(jiān)聽storage的回調不會執(zhí)行,后面我也試過各種辦法,比如在定時器里循環(huán)去獲取localStorage中的值,使用Service Worker等均無法實現,這應該是瀏覽器為了安全考慮進行了限制。
如果有想要看兩個跨域頁面在本地實現量子糾纏效果的同學,可以自行到我GitHub上下載visualization-collection和michelle-design這兩個項目代碼,然后在本地運行,就可以看到效果啦。
五、結語
該終極方案與我的另一篇文章《兩個跨越頁面進行跳轉傳參的終極方案》中的終極方案有異曲同工之妙,都是通過在原先的頁面中無痕嵌入另一個頁面,然后通過myIframe.contentWindow.postMessage來發(fā)送消息,如此實現跨域信息的傳遞。兩個不同窗口打開的同域頁面,則通過將信息保存到localStorage,另一頁面通過監(jiān)聽storage改變的方式傳遞信息。
到此這篇關于JS實現兩個跨域頁面實現量子糾纏互動效果的文章就介紹到這了,更多相關JS跨域頁面互動內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javascript的解析執(zhí)行順序在各個瀏覽器中的不同
javascript是一種解釋型語言,它的執(zhí)行是自上而下的。由于各個瀏覽器對它的理解有所差異,所以我們有必要深入理解js的執(zhí)行順序2014-03-03
僅IE9/10同時支持script元素的onload和onreadystatechange事件分析
測試結果可以看出,IE9后已經開始支持script的onload事件了。一直以來我們判斷js文件是否已經加載完成就是用以上的兩個事件。2011-04-04

