提问人:mgreen 提问时间:8/9/2023 最后编辑:mgreen 更新时间:8/14/2023 访问量:260
在 Firefox 和 Safari 中共享 iframe 和页面之间的本地存储 - Vanilla JavaScript
Share Local storage between iframe and page in Firefox and Safari - Vanilla JavaScript
问:
您能帮忙解决以下问题吗?domaina.com/parent.html 包含一个 src=domainb.com/iframe.html 的 iframe。当我们单击 domaina.com/parent.html 上的按钮时,我们使用 postMessage 和 localStorage 将 URL 传递给 iframe。我们将有多个具有不同 URL 的按钮。然后,我们被重定向到 domainb.com/iframe.html。然后,我们从 localStorage 检索 URL,并将重定向到该 URL。以下代码在 Chrome 中工作正常,但在 Firefox 和 Safari 中不行;我可以将 URL 从 iframe 保存到 localStorage,但是一旦我被重定向到 iframe 页面,该 URL 就不在 domainb.com 上的 localStorage 中。添加查询参数不是一个选项。
父级.html:
<!DOCTYPE html>
<html>
<head>
<title>Parent Window</title>
</head>
<body>
<iframe id="iframe-id" src="https://domainb.com/iframe.html" width="500" height="200">
</iframe>
<div class="button" role="button" tabindex="0" style="cursor:pointer">Click Me</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('.button').addEventListener('click', (event) => {
setTimeout(() => {
const iframeDomain = 'https://domainb.com'; // Set the correct iframe domain here
const data = doSomethingToGetData();
const iframe = document.getElementById('iframe-id');
// Send data to the iframe to save
iframe.contentWindow.postMessage({
action: 'save',
key: 'myKey',
value: data
}, iframeDomain);
// Request data from the iframe
iframe.contentWindow.postMessage({
action: 'get',
key: 'myKey'
}, iframeDomain);
window.addEventListener("message", messageHandler, false);
function messageHandler(event) {
console.log(event)
if (event.origin !== iframeDomain) {
return; // Reject messages from unknown origins
}
const { action, key, value } = event.data;
if (action == 'returnData') {
useData(key, value);
}
}
// Function to simulate getting data
function doSomethingToGetData() {
return "https://redirect.com";
}
// Function to handle the returned data from the iframe
function useData(key, value) {
console.log('Received Data Key:', key);
console.log('Received Data Value:', value);
}
location.href = 'https://domainb.com/iframe.html';
}, 2000);
});
});
</script>
</body>
</html>
iframe.html
<!DOCTYPE html>
<html>
<head>
<title>Iframe Window</title>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const domains = [
"https://domaina.com", // Add parent domain to the whitelist
"https://domainb.com"
];
window.addEventListener("message", messageHandler, false);
// Check if the page is the top-level window (not inside an iframe)
if (window === window.top) {
window.location.href = getDataFromLocalStorage("myKey");
}
function messageHandler(event) {
if (!domains.includes(event.origin))
return;
const { action, key } = event.data;
if (action === 'save') {
const value = event.data.value;
saveDataToLocalStorage(key, value);
} else if (action === 'get') {
const value = getDataFromLocalStorage(key);
event.source.postMessage({
action: 'returnData',
key,
value
}, event.origin);
}
}
// Function to save data to localStorage
function saveDataToLocalStorage(key, value) {
window.localStorage.setItem(key, JSON.stringify(value));
}
// Function to get data from localStorage
function getDataFromLocalStorage(key) {
const value = window.localStorage.getItem(key);
return value ? JSON.parse(value) : null;
}
});
</script>
</body>
</html>
答:
0赞
mgreen
8/14/2023
#1
我有我自己问题的答案:
在 iframe.html 上添加了一个带有操作“dataSaved”的 postMessage,以响应数据已保存的父级:
//existing code
if (action === 'save') {
const value = event.data.value;
saveDataToLocalStorage(key, value);
// Respond back to the parent that data has been saved
event.source.postMessage({
action: 'dataSaved',
key,
value
}, event.origin);
}
//existing code
on parent.html 添加了一个侦听器,用于在接收数据后导航到新 URL:
//existing code
if (action == 'returnData') {
useData(key, value);
} else if (action === 'dataSaved') {
// After receiving data, navigate to the new URL
location.href = value;
}
//existing code
评论
saveDataToLocalStorage("myKey", getDataFromLocalStorage("myKey"))
beforeunload
setTimeout(…, 2000)