问题在于该代码中,当在
popup
设置新的
.location.href
后,立即调用
.postMessage()
,而不等待
window
上的
load
事件。
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
为了达到预期的结果,您可以从原始
window
('index.html')控制过程。每个
window.name
都设置为唯一值。当在
"http://domain_one.com"
提交
<form>
后,生成的
FormData
可以转换为
ArrayBuffer
并传输到
index.html
,然后
popup
(
a.html
)的
location.href
设置为
"http://domain_two.com"
。在
b.html
的
load
事件中,将
window
的
name
用
.postMessage()
发送到
index.html
。然后,
FormData
被传递给
.postMessage()
,其中
b.html
获取最初在
b.html
提交的
FormData
。
(下面的代码可能需要调整
origin
检查。该代码已在plnkr上进行了测试,在那里模拟跨域消息传递不是1:1,但应提供如何完成要求的模式)。
index.html (opener
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
const popup = window.open('a.html');
const [firstName, lastName] = [...Array(2)].map(_ => new Uint32Array(16));
[firstName, lastName].forEach(buffer => window.crypto.getRandomValues(buffer));
const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];
const [first, last] = [firstName, lastName].map(buffer => decoder.decode(buffer));
popup.name = first;
let data;
window.addEventListener("message", e => {
if (e.source.name === first) {
console.log(e.source.name);
data = decoder.decode(e.data);
console.log(e, JSON.parse(decoder.decode(e.data)));
popup.name = last;
popup.location.href = "b.html";
}
if (e.source.name === last) {
let curr = encoder.encode(data);
console.log(e.source.name, e.data);
e.source.postMessage(curr.buffer, e.source.location.href, [curr.buffer]);
}
})
</script>
</body>
</html>
a.html (弹出窗口
, "http://domain_one.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
a
<form>
<input name="input">
<input type="submit">
</form>
<script>
document.forms[0].onsubmit = e => {
// prevent default `form` submission
e.preventDefault();
// pass `form` to `FormData`
const formData = new FormData(e.target);
// encode `formData` as a `Uint8Array`
const encoded = new TextEncoder().encode(JSON.stringify([...formData.entries()]));
console.log(encoded);
// transfer `encoded` to `opener` (`index.html`)
opener.postMessage(encoded.buffer, opener.location.href, [encoded.buffer]);
}
</script>
</body>
</html>
b.html (popup
, "http://domain_two.com"
)
b.html(弹出窗口
,"http://domain_two.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
b
<script>
const decoder = new TextDecoder();
let data;
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== opener.location.origin)
return;
console.log(event);
data = JSON.parse(decoder.decode(event.data));
p.textContent = JSON.stringify(data, null, 2);
}
onload = () => {
opener.postMessage("ok", opener.location.href);
}
</script>
<pre id="p"></pre>
</body>
</html>
plnkr
"http://domain_two.com"
已加载完成?在问题的代码中,popup.location.href="http://domain_two.com"
之后立即调用popup.postMessage(JSON.stringify(formData),"http://domain_two.com")
。 - guest271314Storage
、history
、MessageChannel
和iframe
元素或者SharedWorker
、ServiceWorker
进行通信。或者通过将window.open()
替换为设置popup
.href
,与opener
进行通信。本质上,问题中的代码试图向自身发送postMessage()
。最简单的方法是在新窗口的load
事件中解析查询字符串。 - guest271314