chevron-left chevron-right

Piotr Nalepa Frontend, architecture and AI

[HTML5] Jak komunikować się między stronami za pomocą HTML5 postMessage API

This version
blog.piotrnalepa.pl/2013/06/24/html5-jak-komunikowac-sie-miedzy-stronami-za-pomoca-html5-postmessage-api
Published
Author
, Staff Software Engineer
Category
HTML5
Feedback
Write to me · Post on X

This post is 13 years old. Browsers and tools may have changed since then, so check the code against current documentation before you use it.

Specyfikacja HTML5 zawiera wiele różnych API. Jednym z nich jest API do komunikowania się stron umieszczonych w ramkach (iframe) ze stroną główną. Tego typu komunikacja może być bardzo przydatna w różnego rodzaju aplikacjach internetowych i nie tylko, gdzie istnieje potrzeba komunikacji między zupełnie różnymi stronami znajdującymi się w różnych domenach.

W skrócie, window.postMessage API zachowuje się jak AJAX bez odwoływania się do backendu strony internetowej (na przykład do metod PHP czy też skryptów w node.js).

Section 1HTML5 postMessage API - strona źródłowa

Na początek należy przygotować stronę źródłową/główną, która będzie wysyłała wiadomości za pomocą postMessage API. Zaczniemy od kodu HTML:

Example 1HTML
1
2
3
4
5
6
7
8
9
<form id="login" action="/">
<ul>
  <li><label for="username">Nazwa użytkownika:</label><input type="text" name="login" id="username"></li>
  <li><label for="password">Hasło:</label><input type="password" name="pass" id="password"></li>
  <li><input type="submit" value="Zaloguj"></li>
</ul>
</form>
<iframe id="target" src="[adres-url-ramki]"></iframe>
<p id="answer"></p>

Przygotowano prosty formularz, ktory zawiera 2 pola do wypełnienia i przycisk wyślij. Do tak przygotowanego formularza zastosujemy następujący skrypt:

Example 2JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  window.onload = function () {
    var iframe    = document.getElementById('target').contentWindow;
    var form      = document.getElementById('login');
    var domain    = 'http://demo.piotrnalepa.pl';
 
    form.onsubmit = function (event) {
      event.preventDefault();
 
      var data = {
        user : document.getElementById('username').value,
        pass : document.getElementById('password').value
      };
      iframe.postMessage(data, domain);
 
      event.returnValue = false;
      return false;
    };
 
    window.addEventListener('message', function (event) {
      if (event.origin !== domain) return;
 
      document.getElementById('answer').innerHTML = event.data;
    },false);
  };

Powyższy kod JS jest odpowiedzialny za przesłanie wiadomości do strony znajdującej się w ramce. Wykorzystałem tutaj czysty JS, który na pewno nie zadziała w IE8 i niżej (nie obsługują windows.addEventListener).

Po kliknięciu przycisku, następuje utworzenie obiektu z danymi podanymi przez użytkownika a następnie przesłanie tych danych do strony w ramce za pomocą iframe.postMessage, ktory przyjął 2 argumenty: dane i adres domeny docelowej, czyli adres strony w ramce. Dla strony źródłowej zdefiniowałem zachowanie się strony w momencie, gdy strona wywoła zdarzenie - message. Zdarzenie message jest jednym ze zdarzeń obsługiwanych przez JS, tak jak click, hover, mouseleave, itd. Gdy strona źródłowa otrzyma odpowiedź z ramki, to wyświetli jej treść w kontenerze o identyfikatorze #answer.

Section 2HTML5 postMessage API - strona docelowa/ramka

Teraz pora zająć się stroną docelową, ktora będzie przyjmowala dane z formularza na poprzedniej stronie i ewentualnie będzie mogła sobie je przetworzyć w razie potrzeby. Jej kod HTML wygląda następująco:

Example 3HTML
1
2
<h2>To jest strona na zupełnie innym serwerze.</h2>
<p id="message">A tu będzie przesłana wiadomość</p>

Nic specjalnego, nagłówek oraz paragraf z identyfikatorem. W tamtym paragrafie będzie wyświetlona wiadomość ze strony źródłowej.
Kod JS, który będzie obslugiwal otrzymywanie wiadomości ze strony źródłowej wygląda nastepująco:

Example 4JavaScript
1
2
3
4
5
6
7
8
9
10
window.addEventListener('message', function (event) {
  var message;
  if (event.origin !== 'https://blog.piotrnalepa.pl') {
    message = 'To nie jest wiadomość z bloga https://blog.piotrnalepa.pl<br/>, tylko z: ' + event.origin;
  } else {
    message = 'Oto dane jakie dostarczono: ' + JSON.stringify(event.data) + '<br/> z domeny: ' + event.origin;
	event.source.postMessage('Wiadomość otrzymano :)', event.origin);
  }
  document.getElementById('message').innerHTML = 'Wiadomość:<br/>' + message;
}, false);

Wywołano metodę, ktora nasłuchuje czy nie miało miejsce wydarzenie message, a jeśli tak to sprawdza czy adres strony źródlowej się zgadza z adresem zdefiniowanym w kodzie JS strony docelowej. To jest zabezpieczenie przed niepożądanymi zapytaniami z innych stron. W zależności od tego czy adres strony źródłowej się zgadza następują inne akcje (w tym przypadku, generowana jest inna wiadomość). Następnie, do kontenera o identyfikatorze #message wstawiana jest treść wiadomości, a na końcu następuje wysłanie wiadomości zwrotnej do strony źródłowej, że wiadomość otrzymano. Należy zwrócić uwagę, że adres strony źródłowej jest zawarty w event.source i to na nim wykonujemy akcję postMessage.

Section 3HTML5 postMessage API - podsumowanie

Jak widać, nie trzeba koniecznie wykonywać zapytań AJAX-owych aby otrzymać dane z innych stron. Można równie dobrze wykorzystać do tego postMessage API. Dzięki temu, cała akcja dzieje się po stronie frontendu, czyli przeglądarki użytkownika. W podstawowym założeniu, miało to na celu uniknięcie wykonywania zapytań AJAX do skyptów serwerowych, jeśli istniała możliwość przechowywania potrzebnych danych w wygenerowanej ramce.

Mam nadzieję, że będzie to przydatny tekst i pozwoli Ci to na stworzenie wielu ciekawych funkcjonalności w oparciu o tą technologię, która jest właściwie wspierana we wszystkich popularnych przeglądarkach.

Przeglądarka wsparcie
Mozilla Firefox tak
Google Chrome tak
Opera nie
Safari tak
Internet Explorer

7/8/9/10

nie/tak/tak/tak

Demo z tego artykułu można zobaczyć tutaj: HTML5 postMessage demo

źródło

Share
Feedback

About the author

Staff Software Engineer

I've been writing this blog since 2009 and building for the web professionally for 14 years. Today I lead the frontend of the Cosmos platform at Bishop Fox, where I've been since day one of the project. Before that I worked at OLX, KUDO, Auto1 and eZ Systems. Here I write about what I've learned in practice: JavaScript, TypeScript, React, CSS and frontend architecture. I've also spoken at conferences across Poland and Europe. Got a question or an idea for a post? Let me know!