Web 開發中,有時我們需要實現不同頁面之間的數據傳遞和事件觸發,比如一個頁面打開了另一個頁面,然后在新的頁面中操作后需要更新原來的頁面的內容。這種場景在電商、支付、社交等領域都很常見,那么如何用js來實現不同頁面之間的交互呢?本文提供幾種常見的方法供大家學習參考!
在 Web Storage 中,每一次將一個值存儲到本地存儲時,都會觸發一個 storage 事件,通過 localStorage 結合 window.addEventListener('storage', cb) 完成 A、B 標簽頁間通信。
// A標簽頁
localStorage.setItem('send-msg', JSON.stringify({
name: 'hzd',
age: '18',
}))
// B標簽頁
window.addEventListener('storage', (data) => {
try {
console.log(data)
const msg = JSON.parse(data.newValue)
} catch (err) {
// 處理錯誤
}
})
在控制臺打印一下 data 的值,可以看到挺多信息:
BroadcastChannel 通信方式的原理就是一個命名管道,它允許讓指定的同源下瀏覽器不同的窗口來訂閱它。
每個 BroadcastChannel 對象都需要使用一個唯一的名稱來標識通道,這個名稱在同一域名下的不同頁面之間必須是唯一的,它允許同一域名下的不同頁面之間進行通信。
通過 postMessage 方法,一個頁面可以將消息發送到頻道中,而其他頁面則可以監聽 message 事件來接收這些消息。通過這種方式是短線了一種實時通信的機制,可以在不同的頁面之間傳遞信息,實現頁面間的即時交流。如下圖所示:
// A頁面
const bc = new BroadcastChannel("test_channel");
bc.postMessage("This is a test message.");
// B頁面
const bc = new BroadcastChannel("test_channel");
bc.onmessage = (event) => {
console.log(event);
};
postMessage 是 H5 引入的 API,該方法允許來自不同源的腳本采用異步方式進行有效的通信,可以實現跨文本文檔、多窗口、跨域消息傳遞,多用于窗口間數據通信,這也使它成為跨域通信的一種有效的解決方案。
下面看兩個簡單的使用例子:
示例一:
// 發送端:
<button id="btn">發送消息</button>
<script>
let device = window.open('http://localhost:63342/signal_communication/postMessage/receive.html')
document.getElementById('btn').addEventListener('click', event => {
device.postMessage('發送一條消息')
})
</script>
// 接收端:
<script>
window.addEventListener('message', event => {
console.log(event)
})
</script>
示例二:
// 發送端:
<div>
<input id="text" type="text" value="Runoob" />
<button id="sendMessage" >發送消息</button>
</div>
<iframe id="receiver" src="https://c.runoob.com/runoobtest/postMessage_receiver.html" width="300" height="360">
<p>你的瀏覽器不支持 iframe。</p>
</iframe>
<script>
window.onload = function() {
let receiver = document.getElementById('receiver').contentWindow;
let btn = document.getElementById('sendMessage');
btn.addEventListener('click', function (e) {
e.preventDefault();
let val = document.getElementById('text').value;
receiver.postMessage("Hello "+val+"!", "https://c.runoob.com");
});
}
</script>
// 接收端:
<div id="recMessage">Hello World!</div>
<script>
window.onload = function() {
let messageEle = document.getElementById('recMessage');
window.addEventListener('message', function (e) { // 監聽 message 事件
alert(e.origin);
if (e.origin !== "https://www.runoob.com") { // 驗證消息來源地址
return;
}
messageEle.innerHTML = "從"+ e.origin +"收到消息: " + e.data;
});
}
</script>
SharedWorker 是一種在 Web 瀏覽器中使用的 Web API,它允許不同的瀏覽上下文,如不同的瀏覽器標簽頁之間共享數據和執行代碼。它可以用于在多個瀏覽上下文之間建立通信通道,以便它們可以共享信息和協同工作。
與普通的 Worker 不同,SharedWorker 可以在多個瀏覽上下文中實例化,而不僅限于一個單獨的瀏覽器標簽頁或框架。這使得多個瀏覽上下文可以共享同一個后臺線程,從而更有效地共享數據和資源,而不必在每個標簽頁或框架中都創建一個獨立的工作線程。
<!-- a.html -->
<script>
let index = 0;
const worker = new SharedWorker("worker.js");
setInterval(() => {
worker.port.postMessage(`moment ${index++}`);
}, 1000);
</script>
<!-- b.html -->
<script>
const worker = new SharedWorker("worker.js");
worker.port.start();
setInterval(() => {
worker.port.postMessage("php是世界上最好的語言");
}, 1000);
worker.port.onmessage = function (e) {
if (e.data) {
console.log(e.data);
}
};
</script>
創建一個 worker.js 文件,并編寫以下代碼:
let data = "";
self.onconnect = (e) => {
const port = e.ports[0];
port.onmessage = function (e) {
if (e.data === "php是世界上最好的語言") {
port.postMessage(data);
data = "";
} else {
data = e.data;
}
};
};
最終代碼運行效果如下圖所示:
Service Worker 它是一種服務工作線程,是一種在瀏覽器背后運行的腳本,用于處理網絡請求和緩存等任務。它是一種在瀏覽器與網絡之間的中間層,允許開發者攔截和控制頁面發出的網絡請求,以及管理緩存,從而實現離線訪問、性能優化和推送通知等功能。
它在瀏覽器背后獨立運行與網頁分開,這意味著即使用戶關閉了網頁,Service Worker 仍然可以運行。可以用于實現推送通知功能。它可以注冊為推送消息的接收者,當服務器有新的通知要發送時,Service Worker 可以顯示通知給用戶,即使網頁沒有打開。
要想使用,首先我們創建兩個不同的 html 文件分別代表不同的頁面,創建一個 Service Worker 文件,并且使用 live server 開啟一個本地服務器:
<!-- a.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
navigator.serviceWorker.register("worker.js").then(() => {
console.log("注冊成功");
});
setInterval(() => {
navigator.serviceWorker.controller.postMessage({
value: `moment ${new Date()}`,
});
}, 3000);
navigator.serviceWorker.onmessage = function (e) {
console.log(e.data.value);
};
</script>
</body>
</html>
<!-- b.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
navigator.serviceWorker.register("worker.js").then(() => {
console.log("注冊成功");
});
setInterval(() => {
navigator.serviceWorker.controller.postMessage({
value: `moment ${new Date()}`,
});
}, 3000);
navigator.serviceWorker.onmessage = function (e) {
console.log(e.data.value);
};
</script>
</body>
</html>
創建一個 worker.js 文件并編寫以下代碼:
// worker.js
self.addEventListener("message", function (e) {
e.waitUntil(
self.clients.matchAll().then(function (clients) {
if (!clients || clients.length === 0) {
return;
}
clients.forEach(function (client) {
client.postMessage(e.data);
});
})
);
});
最終代碼運行如下圖所示:
你所編寫的 Service Worker 將遵守以下生命周期:
IndexedDB 是一種在瀏覽器中用于存儲和管理大量結構化數據的 Web API。它提供了一種持久性存儲解決方案,允許 Web 應用程序在客戶端存儲數據,以便在不同會話、頁面加載或瀏覽器關閉之間保留數據。
與傳統的 cookie 或 localStorage 等存儲方式不同,IndexedDB 更適合存儲復雜的、結構化的數據,例如對象、數組、鍵值對等。這使得它特別適用于應用程序需要存儲大量數據、執行高級查詢或支持離線工作的情況。
要實現跨標簽通信,如下代碼所示:
<!-- a.html -->
<script>
let index = 0;
// 打開或創建 IndexedDB 數據庫
const request = indexedDB.open("database", 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const objectStore = db.createObjectStore("dataStore", {
keyPath: "key",
});
};
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(["dataStore"], "readwrite");
const objectStore = transaction.objectStore("dataStore");
// 存儲數據
objectStore.put({ key: "supper", value: `moment` });
transaction.oncomplete = () => {
db.close();
};
};
</script>
<!-- b.html -->
<script>
// 打開相同的 IndexedDB 數據庫
const request = indexedDB.open("database", 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(["dataStore"], "readonly");
const objectStore = transaction.objectStore("dataStore");
// 獲取數據
const getRequest = objectStore.get("supper");
getRequest.onsuccess = (event) => {
const data = event.target.result;
if (data) {
console.log(data.value);
}
};
transaction.oncomplete = () => {
db.close();
};
};
</script>
最終代碼運行如下圖所示:
<!-- a.html -->
<script>
let index = 0;
setInterval(() => {
document.cookie = `supper=moment ${index++}`;
}, 1000);
</script>
<!-- b.html -->
<script>
console.log("cookie 的值為: ", document.cookie);
setInterval(() => {
console.log("cookie 的值發生了變化: ", document.cookie);
}, 1000);
</script>
具體代碼運行效果如下圖所示:
作者:前端掘金者H
鏈接:https://juejin.cn/post/7268602250653319202
幾天做一個web項目有這樣一個需求,web項目是一個后臺管理系統,在使用系統時會打開很多標簽頁,每個標簽頁就是一個iframe打開的一個新的html頁面,現在需要在每個標簽頁之間互相通信、互相調用方法。例如:打開了A,B,C三個標簽頁,我在C頁面把數據修改了,我要通知A,B兩個頁面的數據也要更新到最新修改的數據。
在網上看到的解決辦法都是用iframe 父頁面與子頁面互相調用方法,但是用這種方法感覺一點都不靈活,不是很好用,有很大的局限性。
后來在使用localStorage存儲的時候發現localStorage有這樣一個特性。
在A界面監聽storage事件。
window.addEventListener("storage", function (e) {
alert(e.key+'='+e.newValue);
});
在B頁面修改或添加了localStorage。
localStorage.setItem('key', 'value');
然后A界面的監聽事件里就可以接收到通知。
利用這個特性我封裝了一個JS,代碼如下:
用法很簡單,在所有頁面都引入上面的JS,然后在A,B頁面添加監聽事件。
C頁面對數據進行了修改后就發一個通知給A,B頁面,讓A,B頁面進行相應的操作。
就這樣一個多頁面之間互相通信調用的JS就封裝好了,iframe與iframe之間的頁面可以互相通信調用。瀏覽器每個標簽頁之間的頁面也可以互相通信調用。
不過需要注意以下幾點:
1、 互相通信調用之間的幾個頁面要放在服務器環境,例如放在IIS或者tomcat之類的服務容器里。
2、 打開的幾個頁面要是同源頁面,也就是幾個頁面之間IP相同,端口相同。
3、 打開的幾個頁面必須是在同一個瀏覽器。
4、 發送通知傳的參數現在還只能是字符串,如果要傳JSON類型,請先在C頁面轉字符串,在A,B接收到通知后,再把字符串轉回JSON。
5、同一個頁面接收不到同一個頁面發送的通知,當然誰也不會做這種事,在同一個頁面接收同一個頁面發送的通知。
ultrin是一個多窗口管理工具。軟件基于Electron和React等開發的多標簽頁管理軟件,使用它之后幫助用戶將各個不同程序的窗口整合在一個窗口中,幫助你高效的整理雜亂的桌面。軟件使用類似一個打開了多個標簽頁的瀏覽器,它將各個不同的程序都放置在一個單獨的標簽頁,這樣用戶可以像切換網頁一樣,快速切換各個程序窗口。軟件使用方便,可以快速切換每個程序,讓辦公更加高效。軟件提供多種切換模式,你可以用鼠標點擊標簽來切換,也可以使用Ctrl+Tab與Ctrl+Shift+Tab鍵盤快捷鍵來切換,十分便捷。
下載地址:https://www.downkuai.com/soft/118112.html
1、運行Multrin綠色版后會提示你拖放窗口進去,你需要將窗口拖放到軟件界面接近頂部位置,看到軟件界面頂部出現標簽頁了就可以松開鼠標了。如此反復操作,你就可以將多個窗口放置到同一個窗口中了。這里支持包括UWP、Windows窗口空間以及其他第三方的窗口界面添加。
2、添加窗口時無法調整標簽的位置,但添加后你就可以拖動標簽來進行位置調整了。窗口大小方面,你可以調整軟件內軟件窗口大小(不是軟件窗口大小),而軟件窗口大小會根據你調節標簽頁軟件的大小而變化。
3、軟件同樣也支持快捷鍵,使用「Ctrl+Tab」可以快速在標簽頁中進行切換。當關閉軟件窗口時,會保留當前你正在瀏覽的標簽頁窗口,其他的標簽頁窗口都會被關閉掉。最后在右上角還支持亮色和暗色主題的切換。
1、Multrin 可以支持添加包括 UWP 和傳統的 Windows 窗口,甚至大部分第三方自制界面的應用比如 TIM 等也能順利添加;
2、將應用程序添加到 Multrin 的多標簽頁組之后,你可以使用鼠標拖動標簽頁來調整位置排序;
3、在調整軟件窗口大小后,Multrin 也會自動根據大小自動適應變化的;
4、你可以隨時將新的應用程序窗口拖進來 Multrin 里,也能將當前的程序拖出去;
5、你將軟件所在的標簽頁關閉的同時也會關閉程序;
6、當你關閉整個 Multrin 時,它會保留當前你正在瀏覽的標簽頁的程序,其他的標簽頁對應的軟件則會全部一次性關掉。
1、在Multrin上拖放應用程序并在單個窗口中進行管理
此應用程序背后的主要工作原理是選項卡式界面,類似于經典的Internet瀏覽器之一。用戶所需要做的就是將他們的應用程序疊加到界面上,然后將其保留在其中,并嵌套在組織整齊的標簽中。
但是,拖放過程存在一個陷阱,那就是需要將應用程序從其標題欄中拖動的事實,因為不支持直接從任務欄中獲取這些應用程序。盡管如此,這并不是一個重大的交易突破點,但它確實是該應用程序功能的不錯的補充。
2、一個選項卡式布局,可以重新定位,但缺乏雙視角
將應用程序添加到瀏覽界面后,即可在相應的選項卡中使用它們,這些選項卡通過選項卡的標題欄樣式可提供其內容的輕微預覽。但是,在鼠標懸停時具有“偷看”類型的預覽將是有益的補充。
另外,由于這是一個應用程序組織軟件,因此一個很快變得很明顯的缺點是缺乏堆疊標簽和應用程序本身的能力。水平或垂直;沒有雙景。對于要求更高的用戶而言,這可能是個問題。
3、Windows選項卡瀏覽功能的一個有趣替代方法,它將提高用戶的工作效率
該軟件將允許人們使用選項卡式界面來管理他們的應用程序,該界面將使所有事物保持井井有條。盡管它為打開的應用程序設法提供了比內置Windows選項卡瀏覽更好的替代方法,但是由于缺少雙視圖和更好的選項卡預覽,因此可靠性較低。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。