Tab inter page communication

Keywords: Front-end

1, Scene

There are different scenarios for inter Tab communication:

  • Communication between Tab pages under homologous websites
  • Tab page communication under non homologous websites

2, Communication mode between Tab pages under homologous websites

According to the characteristics of communication, it is divided into three modes: point-to-point communication, broadcast communication and polling communication

  • Point to point communication
    • window.postMessge
  • Broadcast communication
    • BroadCast Channel
    • Service Worker
    • LocalStorage
  • Polling communication
    • IndexedDB

2.1 window.postMessge

When opening a new page with window.open, if active communication is required between two tabs, you can use window.postMessage to realize communication.

Scenario: open page B with window.open on page A, and send A message to page A on page B.

Features: similar to point-to-point communication, other homologous pages cannot receive messages.

Principle:

  • Page A listens for message events
  • The B page uses postMessage to send messages
  • Page B can obtain the window object of page A, generally using window.opener

Concrete implementation( Source code):

A page listening message

/**
 * Event mapping
 */
const eventMap: PlainObject = {};

window.addEventListener('message', (ev) => {
  let { data } = ev;
  if (Object.prototype.toString.call(data) !== '[object Object]') return;

  let { key, args = [] } = data;
  let fn = eventMap[key];
  if (typeof fn === 'function') {
    if (!Array.isArray(args)) args = [args];
    fn(...args);
  }
});

/**
 * Register Tab page events
 *
 * @param key
 * @param fn
 */
export function registerTabEvent(key: string, fn: (...args: any[]) => void) {
  eventMap[key] = fn;
}

B page send message

type TMessage = { key: string; args?: any[] };
/**
 * send message
 *
 * @param data
 * @returns
 */
export function sendTabMessage(data: TMessage) {
  let opener = window.opener;
  if (!opener) return;

  opener.postMessage(data, '/');
}

2.2 BroadCast Channel

The BroadcastChannel interface proxies a named channel and allows any browsing context under the specified origin to subscribe to it. It allows different browser windows, Tab pages, frames or different documents under iframe of the same origin to communicate with each other. By triggering a message event, the message can be broadcast to all BroadcastChannel objects listening to the channel.

characteristic:

  • Broadcast communication

Principle:

  • Page to create a BroadCast Channel instance
  • Register the message event for the instance

realization:

Demo

export default defineComponent({
  setup() {
    const instr = ref('');
    const outmsg = ref('');

    let bc = new BroadcastChannel('test');
    bc.onmessage = (ev) => {
      outmsg.value = ev.data;
    };

    const sendMsg = () => {
      bc.postMessage(instr.value);
    };

    return {
      instr,
      outmsg,
      sendMsg,
    };
  },
});

2.3 Service Worker

Service Worker is a Worker running in the background. Multiple pages can share the Worker. The Worker is used as the message forwarding center to realize the communication between multiple pages.

Principle:

  • Multiple tabs share the same Service Worker. Each Tab is a Client. The Service Worker pushes messages to each Client to realize communication

realization:

Demo

ServiceWorker registers the message event

// Register the message event in the ServiceWorkerGlobalScope context
// When the supervisor hears the message, it is forwarded to each client
self.addEventListener('message', function (ev) {
  ev.waitUntil(
    self.clients.matchAll().then(function (clients) {
      if (!clients || clients.length === 0) {
        return;
      }

      // Send a message to each client, including itself
      clients.forEach(function (client) {
        client.postMessage(ev.data);
      });
    }),
  );
});

Receive and send messages at the client

export default defineComponent({
  setup() {
    const instr = ref('');
    const outmsg = ref('');

    const sendMsg = () => {
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.controller?.postMessage(instr.value);
      }
    };

    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('./tab-message.sw.js').then((data) => {
        console.log('Service Worker login was successful');
      });

      navigator.serviceWorker.addEventListener('message', (ev) => {
        outmsg.value = ev.data;
      });
    } else {
      console.log('Browser does not support serviceWorker');
    }

    return {
      instr,
      outmsg,
      sendMsg,
    };
  },
});

2.4 LocalStorage

Localstorage can store browser data and share data when there is a same source. When two Tab pages under the same source need to listen to each other's data changes, using localstorage is a better way.

Principle:

  • Two Tab pages are homologous
  • A page listening storage
  • When page B uses setItem to update data, page A can listen for changes in localstorage data

realization:

window.addEventListener('storage', function (e) {
  console.log(e.key, e.newValue);
});

2.5 IndexedDB

Tab s under the same source can access the same IndexedDB and realize communication by using the global storage characteristics of data.

Principle:

  • A page stores data in IndexedDB
  • B page polls and queries the changes of data in IndexedDB

Based on the same principle, both local storage and session storage can adopt this scheme

3, Communication between non homologous pages

  • iframe

3.1 iframe

The communication between non homologous pages can be realized by using iframe as the medium

Posted by cliftonbazaar on Thu, 16 Sep 2021 18:19:41 -0700