Обмен сообщениями iframe с API PostMessage
Существует множество статей, описывающих API PostMessage и тот факт, что фреймам из другого источника трудно взаимодействовать со страницей и объектом окна этой страницы.
Здесь не будут подробно описываться концепции доступа между источниками или API PostMessage. Это будет краткий «учебник», демонстрирующий, как мы можем использовать API PostMessage для связи между страницей и Iframe, обслуживаемым из другого домена.
Давайте начнем!
Итак, основная проблема, которую мы пытаемся решить, заключается в следующем.
- У нас есть обычная страница с iframe, размещенным в другом домене.
- iframe должен получить доступ к глобальной переменной на странице, в которую он встроен.
iframe
Сначала мы можем создать базовую HTML-страницу, выглядящую так (давайте назовем эту страницу IFRAME)
Это довольно просто. Часть сценария ищет глобальную переменную «key1», которой не существует.
<script>
const title = document.getElementById('titleId');
const keyTolookFor = 'key1';
title.innerText =
globalThis[keyTolookFor] ||
`Could not find |${keyTolookFor}| key in the global scope`;
</script>
Теперь мы собираемся встроить приведенный выше код на другую страницу, которая имеет переменную «key1» в глобальной области видимости. Эта страница для этого примера точно такая же, как и приведенная выше, с той лишь разницей, что переменная «key1» доступна в глобальной области видимости и включает в себя страницу «THE IFRAME».
Как видно из приведенного выше примера, iframe не может напрямую обращаться к глобальной переменной «key1». К счастью, мы можем использовать API PostMessage , чтобы получить значение ключа. Тот же метод можно использовать для всех видов связи между iframe и главной страницей.
Решение с использованием PostMessage API
Чтобы немного упростить работу с API, я создал этот шаблонный код, который можно использовать в качестве отправной точки, поэтому с API PostMessage намного проще работать, особенно если вы ожидаете прослушивания многих событий. В этом простом случае это может быть немного излишним, но он все равно выполнит свою работу без особых накладных расходов. Бланк выглядит так
const actions = {};
const handler = (event) => {
if (event.data) {
const type = event.data.type;
const cmd = actions[type];
if (cmd) {
for (let i = 0; i < cmd.length; i++) {
cmd[i](event.data.payload, event.source);
}
}
}
};
const connect = (type, callback) => {
const cmd = (actions[type] = actions[type] || []);
cmd.push(callback);
};
const dispatch = (target, message) => {
if (target && target.postMessage) {
target.postMessage(message, '*');
}
};
window.addEventListener('message', handler, false);
Для решения описанной выше проблемы мы собираемся отправить сообщение из iframe, которое позволит нашей главной странице узнать, что iframe запрашивает некоторую информацию. Такой запрос может выглядеть так:
dispatch(window.top, {
type: 'GET_VARIABEL', // Whatever eventname you can come up with
payload: { key: 'key1' } // some payload the listener (mainpage) can read
});
const mainpageHandler = (input, source) => {
const { key } = input; // key1
};
connect('GET_VARIABEL', mainpageHandler);
С помощью этой техники мы можем отправлять сообщения туда и обратно между двумя «контекстами», тем самым получая доступ ко всему, к чему имеет доступ главная страница, из iframe. Следует отметить, что когда главная страница должна отправить сообщение обратно в iframe, нам нужно указать правильный контекст, куда мы хотим отправить сообщение. Это можно легко сделать, изменив указанный выше mainpageHandler на этот
const mainpageHandler = (input, source) => {
const { key } = input; // key1
dispatch(source.window, { // <-------------------- THIS
type: 'VARIABLE_RESPONSE', // The iframe then needs to listen for this event
payload: { key, value: window[key] }, // The variable from the main page scope
});
};
connect('GET_VARIABEL', mainpageHandler);
И главную страницу можно изменить, чтобы она выглядела так
Чтобы увидеть, как это работает, вам нужно открыть страницу в окне за пределами Blitzstack.
Вы можете открыть страницу результатов здесь
У него много приложений, и я думаю, что это один из лучших способов связи между iframe и главной страницей.
Спасибо!
Больше контента на PlainEnglish.io .
Подпишитесь на нашу бесплатную еженедельную рассылку . Следите за нами в Twitter , LinkedIn , YouTube и Discord .
Повышайте осведомленность и внедряйте свой технологический стартап с помощью Circuit .

![В любом случае, что такое связанный список? [Часть 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































