You need to enable JavaScript to run this app. React与Next.js中如何使用postMessage和addEventListener实现iframe通信
优惠活动
大模型
产品
解决方案
定价
更多

React与Next.js中如何使用postMessage和addEventListener实现iframe通信

问题原因

  • origin校验拦截了合法消息:浏览器message事件的origin属性返回值不带末尾斜杠,你代码中校验的https://wyftk.sse.codesandbox.io/多了末尾斜杠,所有消息都会被直接拦截,这是最核心的失效原因。
  • 父页面发消息时机可能早于iframe加载完成:未做iframe加载完成判断的情况下,点击按钮发消息时如果iframe内部的监听事件还未挂载,会出现消息丢失。
  • 事件监听未清理:组件卸载时没有移除message事件监听,会导致重复绑定、内存泄漏问题。
  • 不存在你猜测的Next.js环境下React Hook使用addEventListener的兼容问题。

修复后代码

父页面 index.js

import { useRef, useEffect, useState } from "react";

const IndexPage = () => {
  const IFrameRef = useRef(null);
  const [receivedMsg, setReceivedMsg] = useState("");
  // 标记iframe是否加载完成
  const [iframeLoaded, setIframeLoaded] = useState(false);
  // 统一声明origin,避免写错
  const ALLOW_ORIGIN = "https://wyftk.sse.codesandbox.io";

  const sendMessage = () => {
    console.log("send parents msg");
    if (!IFrameRef.current || !iframeLoaded) return;
    IFrameRef.current.contentWindow.postMessage(
      "Hello son",
      ALLOW_ORIGIN
    );
  };

  useEffect(() => {
    const handleMessage = (e) => {
      if (e.origin !== ALLOW_ORIGIN) return;
      setReceivedMsg("child message =" + e.data);
    };
    window.addEventListener("message", handleMessage);
    // 组件卸载时清理监听
    return () => window.removeEventListener("message", handleMessage);
  }, []);

  return (
    <div>
      <h1>parents iframe</h1>
      <button
        type="primary"
        onClick={sendMessage}
        disabled={!iframeLoaded}
      >
        send sms to child
      </button>
      <iframe
        ref={IFrameRef}
        style={{ width: "100%", height: "600px" }}
        src="/model"
        id="calculation"
        title="model"
        onLoad={() => setIframeLoaded(true)}
      ></iframe>
      <p>{receivedMsg}</p>
    </div>
  );
};

export default IndexPage;

子页面 model.js

import { useEffect, useState } from "react";

const ModelPage = () => {
  const [receivedMsg, setReceivedMsg] = useState("");
  const ALLOW_ORIGIN = "https://wyftk.sse.codesandbox.io";

  const sendMessage = () => {
    console.log("send child msg");
    window.parent.postMessage("Hi dad!", ALLOW_ORIGIN);
  };
  useEffect(() => {
    const handleMessage = (e) => {
      if (e.origin !== ALLOW_ORIGIN) return;
      setReceivedMsg("parent message =" + e.data);
    };
    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, []);

  return (
    <div>
      <h2>model page</h2>

      <button type="primary" onClick={sendMessage}>
        send sms to parents
      </button>
      <p>{receivedMsg}</p>
    </div>
  );
};
export default ModelPage;

内容的提问来源于stack exchange,提问作者AlexMoshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 13:45:04