10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

満足袋の1人アドベントカレンダーAdvent Calendar 2022

Day 5

iframeと親ページ間でpostMessageを利用してデータ送受信を行う

Posted at

はじめに

iframe表示部分のクリックイベントを取得するという記事で、iframe内のイベントをiframeのcontentWindowに対しaddEventlistenerを登録して親ページで取得する方法を紹介しました。

この記事ではpostMessageを利用してiframeと親ページ間でやり取りする方法を紹介します。

この記事の対象者

  • ページに埋め込んだiframe要素から情報を取得したい
  • ページに埋め込んだiframe要素と親ページ間で相互間のデータ送受信を行いたい
  • ページにiframe埋め込みをする前提のページを作成して、イベント発生時に親ページに情報を渡したい

iframeと親ページ間のデータ送受信

postMessageを利用した送受信の方法

子ページ

データを親ページに送信する場合

window.parent.postMessage(message, targetOrigin);

// 例
window.parent.postMessage("sample.jpでしか受信出来ないメッセージです", "https://sample.jp");

window.parent.postMessage({
    type: "sample",
    data: {
        message: "誰でも受信できるメッセージです",
    },
}, "*");

const example = {
    type: "example",
    data: {
        message: "JSONで渡すメッセージです",
    }
}

window.parent.postMessage(JSON.stringfy(example), "*");
引数の説明
  • message

他のウィンドウに送られるデータです。
決められた型は無いですが、オブジェクトで渡すことでtypeやdataなど親ページで扱いやすい内容で渡すことが出来ます。

  • targetOrigin

データを送信した際の受け取り側のオリジンを限定することが出来ます。
例えばhttps://sample.jpとした場合は、オリジンがhttps://sample.jpのウィンドウでしかデータは受信出来ません。
postMessageの送信先が決まっている場合はオリジン指定をしましょう。

データを親ページから受信する場合

window.addEventListener("message", (response) => {
    // 取得した内容を利用した処理
}) 

postMessageで送信されたデータを受け取るには、addEventListenerで登録したmessageイベントを検知することで取得することが出来ます。

親ページ

データをiframeで埋め込んだ子ページに送信する場合

const iframeElement = document.querySelector("iframe");
iframeElement.contentWindow.postMessage(message, targetOrigin);

iframeのWindowオブジェクトにアクセスして、先ほどと同じようにpostMessageを実行しています。

データを子ページから受信する場合

window.addEventListener("message", (response) => {
    // 取得した内容を利用した処理
}) 

こちらは子ページで受信する場合と違いありません。


以上がiframeと親ページ間でpostMessageを利用してデータ送受信を行う方法になります。

使用例

以下postMessageの使用例です。iframeと親ページで連携して相互間のデータ受け渡しをする例を紹介します。

確認環境
ソースコード

Videotogif (5).gif

iframeでボタンクリックされた回数を親ページに渡す

iframe

let leftCount = 0;
const leftClick = () => {
    const message = {
        type: "click",
        data: {
            name: "left",
            count: leftCount,
        }
    }
    window.parent.postMessage(message, "*");
    leftCount++;
}

let rightCount = 0;
const rightClick = () => {
    const message = {
        type: "click",
        data: {
            name: "right",
            count: rightCount,
        }
    }
    window.parent.postMessage(message, "*");
    rightCount++;
}

// オリジンが異なるので親ページでは受信出来ない
const originRestricted = () => {
    const message = {
        type: "click",
        data: {
            name: "restricted",
        }
    }
    window.parent.postMessage(message, "https://sample.jp");
}

親ページ

window.addEventListener("message", (response) => {
    if (response.data.type === "click") {
        const data = response.data.data;
        if (data.name === "left") {
            const leftNumberElement = document.querySelector("#left-number");
            leftNumberElement.innerHTML = data.count;
        } else if (data.name === "right") {
            const rightNumberElement = document.querySelector("#right-number");
            rightNumberElement.innerHTML = data.count;
        }
    }
})

親ページで選択された色をiframeで表示する

親ページ

const postColor = (color) => {
    const iframeElement = document.querySelector("iframe");
    const message = {
        type: "color",
        data: {
            color: color,
        }
    }
    iframeElement.contentWindow.postMessage(message, "*");
}

iframe

window.addEventListener("message", (response) => {
    if (response.data.type === "color") {
        const messageAreaElement = document.querySelector(".message-area");
        const createDivElement = document.createElement("div");
        const color = response.data.data.color;
        if (color === "red") {
            createDivElement.className = "red";
        } else if (color === "blue") {
            createDivElement.className = "blue";
        } else if (color === "yellow") {
            createDivElement.className = "yellow";
        }
        messageAreaElement.appendChild(createDivElement);
    }
})
10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?