Exploring the Broadcast Channel API for cross-tab communication title. A gradient background with a JavaScript logo in the bottom-left corner and an icon representing a browser in the top-right corner.
贊助

探索 Broadcast Channel API 用於跨標籤頁通訊

閱讀時間 4 分鐘

Broadcast Channel API 實現了不同瀏覽器視窗、標籤頁、iframe 和 Web Worker 之間的通訊。它為瀏覽器中多個 上下文 之間的資料和行為同步提供了一種簡單高效的方式,從而構建更具響應性和吸引力的 Web 應用程式。

在本文中,我們將探討 Broadcast Channel API 的概念、用法和實際應用。我們還將透過一個實際示例,構建一個小型應用程式,演示如何使用該 API 向不同的標籤頁和視窗傳送訊息。

理解 Broadcast Channel API

Broadcast Channel API 引入了一種機制,允許同一使用者和同一瀏覽器的、同一來源(origin)下的不同上下文之間進行通訊。它基於建立單個共享通道的原理,多個瀏覽器上下文可以隨時加入和離開該通道。

加入後,這些上下文可以透過通道傳送和接收訊息,從而實現無縫的資料交換和事件傳播。這種機制消除了對複雜伺服器端通訊的需求。以下是使用該 API 的簡要說明。

建立或加入頻道

js
const bc = new BroadcastChannel("test_channel");

傳送訊息

js
bc.postMessage("This is a test message");

接收訊息(有關詳細資訊,請參閱 BroadcastChannel: message event

js
bc.onmessage = (event) => {
  console.log(event.data);
  // { method: "add", note: "This is a test message" }
};

構建 Node.js 應用程式

首先,請按照我們上一篇文章中“在 Vultr 上部署伺服器”部分中的步驟部署一個伺服器。接下來,透過 SSH 訪問伺服器終端,併為我們的 Web 應用程式設定一個專案。

我們將使用 Nano 文字編輯器在伺服器上建立和編輯專案檔案。您可以在 快捷鍵備忘單 中查詢 Nano 的使用幫助。我們還將使用 Uncomplicated Firewall (UFW) 來控制允許進出伺服器的流量。在我們的應用程式中,我們使用 Node.js 來提供應用程式的索引,並使用 http-server 執行應用程式。任何其他型別的伺服器,如 Python 和 Apache,也可以達到相同的目的。我們還使用埠 8080,透過 UFW 僅允許透過此埠進入流量。

  1. 建立一個專案目錄,並進入該目錄。

    bash
    mkdir notes-app
    cd notes-app
    
  2. 初始化一個 Node.js 專案。

    bash
    npm init -y
    
  3. 安裝 HTTP 伺服器依賴項。

    bash
    npm install http-server
    
  4. 建立一個 HTML 檔案。

    bash
    nano index.html
    
  5. 將以下程式碼複製並貼上到 index.html 檔案中。

    html
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Note-taking App</title>
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <h1>Note-taking App</h1>
        <div id="noteList"></div>
        <div id="noteForm">
          <label for="noteInput">New note</label>
          <input type="text" id="noteInput" placeholder="A note..." />
          <button id="addNoteButton">Add Note</button>
          <button id="resetNoteButton">Reset Notes</button>
        </div>
        <script src="app.js"></script>
      </body>
    </html>
    
  6. 儲存並退出檔案。

  7. 建立一個 CSS 檔案。

    bash
    nano styles.css
    
  8. 將以下程式碼複製並貼上到 styles.css 檔案中。

    css
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f4f4;
      margin: 0;
      padding: 20px;
    }
    
    h1 {
      color: #333;
      text-align: center;
    }
    
    #noteList {
      display: grid;
      row-gap: 10px;
      background-color: #fff;
      border: 1px solid #ddd;
      border-radius: 5px;
      padding: 10px;
      margin-bottom: 20px;
    }
    
    #noteList div {
      background-color: #f9f9f9;
      border: 1px solid #ddd;
      border-radius: 3px;
      padding: 10px;
    }
    
    #noteForm {
      display: grid;
      column-gap: 10px;
      align-items: center;
      grid-template-columns: max-content 1fr max-content max-content;
    }
    
    #noteInput {
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 3px;
      font-size: 16px;
    }
    
    button {
      padding: 10px 20px;
      background-color: #4caf50;
      color: #fff;
      border: none;
      border-radius: 3px;
      font-size: 16px;
      cursor: pointer;
    }
    
    button:hover {
      background-color: #45a049;
    }
    
  9. 儲存並退出檔案。

實現 Broadcast Channel API

  1. notes-app 目錄中,建立一個 JavaScript 檔案。

    bash
    nano app.js
    
  2. 將以下 JavaScript 程式碼複製並貼上到 app.js 中。

    js
    const noteList = document.getElementById("noteList");
    const noteInput = document.getElementById("noteInput");
    const addNoteButton = document.getElementById("addNoteButton");
    const resetNoteButton = document.getElementById("resetNoteButton");
    
    let notes = [];
    
    function renderNotes() {
      noteList.innerHTML = "";
    
      notes.forEach((note) => {
        const noteItem = document.createElement("div");
        noteItem.textContent = note;
        noteList.appendChild(noteItem);
      });
    }
    
    addNoteButton.addEventListener("click", () => {
      const newNote = noteInput.value.trim();
    
      if (newNote) {
        notes.push(newNote);
        renderNotes();
        noteInput.value = "";
    
        channel.postMessage({ action: "add", note: newNote });
      }
    });
    
    resetNoteButton.addEventListener("click", () => {
      notes = [];
      renderNotes();
    
      channel.postMessage({ action: "reset" });
    });
    
    const channel = new BroadcastChannel("notes-channel");
    
    channel.addEventListener("message", (event) => {
      const { action, note } = event.data;
    
      if (action === "add") {
        notes.push(note);
        renderNotes();
      } else if (action === "reset") {
        notes = [];
        renderNotes();
      }
    });
    
  3. 儲存並退出檔案。

  4. 允許埠 8080 的傳入連線

    bash
    sudo ufw allow 8080
    
  5. 啟動檔案伺服器。

    bash
    npx http-server
    
  6. 訪問應用程式 URL http://<server-ip>:8080

現在您可以並排開啟兩個瀏覽器視窗或標籤頁。在一個頁面上新增一個筆記,您會發現該筆記出現在第二個標籤頁中,而無需重新整理頁面。嘗試重置所有筆記,您會發現筆記從兩個標籤頁中都被刪除了,而無需重新整理。

讓我們看一下我們在 app.js 中編寫的程式碼。renderNotes 函式為每個新增的筆記建立一個元素。addNoteButton 函式允許我們在應用程式中新增筆記,channel.postMessage 將“add”操作廣播到其他視窗或標籤頁。同樣,resetNoteButton 允許我們刪除所有現有筆記,channel.postMessage 將“reset action”廣播到其他視窗或標籤頁。

最後,建立一個名為 'notes-channel' 的新 BroadcastChannel,允許同一來源下不同視窗/標籤頁之間進行通訊。BroadcastChannel 的事件監聽器監聽來自頻道的 message 事件,並根據提供的資訊採取相應的操作。

實際用例和示例

  • 在新聞和媒體網站中
    • 用例:跨多個視窗同步文章的閱讀進度。
    • 示例:使用者可以在一個視窗中開始閱讀文章,並在另一個視窗或標籤頁中從同一點無縫繼續閱讀,從而實現一致的閱讀體驗。
  • 在生產力應用中
    • 用例:在多個上下文之間實現文件或檔案的更改的即時同步。
    • 示例:在協作文字編輯器中,一個使用者所做的更改可以即時廣播到其他上下文。
  • 在社交媒體平臺上
    • 用例:跨多個標籤頁或視窗通知使用者新更新、訊息或通知。
    • 示例:如果使用者為社交媒體平臺打開了多個標籤頁,他們可以在所有上下文中接收即時更新,確保他們不會錯過重要資訊。

總結

在本文中,我們探討了 Broadcast Channel API 的概念、用法和實際實現。我們構建了一個基本的同步筆記應用程式,並學習瞭如何使用 Broadcast Channel API 來構建互聯的 Web 體驗。

這是一篇 Vultr 的贊助文章。Vultr 是全球最大的私營雲計算平臺。Vultr 深受開發者喜愛,已為 185 個國家的 150 萬多客戶提供服務,提供靈活、可伸縮的全球雲計算、雲 GPU、裸金屬和雲端儲存解決方案。瞭解更多關於 Vultr 的資訊。