【问题标题】:How to get iframe's refreshed src after interacting交互后如何获取iframe的刷新src
【发布时间】:2019-10-23 01:55:52
【问题描述】:

我有一个与 Grafana 图形链接的 iframe 标记,它支持交互(通过单击/双击 iframe 在 x 轴上放大/缩小)。

当我在新选项卡上打开 iframe src 的 url 时,我可以与图形交互,并看到我的浏览器的 url 参数不断刷新新的 from/to 值(这表示图形的 x 轴的范围)。不幸的是,当它在 iframe 上时,在任何情况下我都看不到“src”属性的任何变化。我需要将 url 参数更改应用于正在显示的其他图表(同步它们)。

我该如何解决这种情况?

我在 Angular 的 component.html 上的 iframe:

<iframe [src]="url_grafana_primary" width="100%" height="300" frameborder="0"></iframe>

渲染后的 iframe:

<iframe _ngcontent-c8="" frameborder="0" height="300" width="100%" src="http://146.250.180.213/grafana/dashboard-solo/script/script_graph.js?scenario_id=rrc_succ_rate&amp;cell_id=ESICAS23B_ESICAS23&amp;refresh=5s&amp;orgId=1&amp;panelId=4&amp;from=1555045266010&amp;to=1555168469864&amp;var-cell_id=ESICAS23B_ESICAS23&amp;var-scenario_id=ESICAS23B_ESICAS23"></iframe>

一些截图:

您可以看到 src 在两种情况下都保持相同的值。

【问题讨论】:

    标签: javascript html angular iframe grafana


    【解决方案1】:

    src 的属性没有改变,但location 对象的行为应该与 grafana 在 iframe 之外时的行为相同。

    你有两个选择,

    1. 如果 grafana 的 frame 和它的 parent 来自同一个源,您可以使用iframe.contentWindow.location.href 访问 location 对象。
    2. 如果它们的来源不同,你需要在框架和它的父框架之间进行通信,你可以使用postMessage

    查看此示例:https://robertnyman.com/html5/postMessage/postMessage.html

    【讨论】:

    • 能否举个例子说明我如何在 Typescript 上使用 postMessage?
    • 它与 Typescript 无关,它是一个浏览器 API。你在 MDN 中有例子。
    • 我添加了一个例子
    • 好的...所以我的理解是,'postMessage' 机制只有在目标 url 准备好接收此消息时才有效,对吧?如果是这样,据我所知,我无法准备 Grafana(iframe 的服务器)来响应此消息,因为我没有开发它。请尽可能纠正我。
    • 另外,有一条随机消息,我收到此错误:“无法在 'DOMWindow' 上执行 'postMessage':提供的目标原点 ('146.250.180.213') 与收件人窗口的原点不匹配 ( 'localhost:4201')。”
    【解决方案2】:

    您可以检测到onload 事件,但要获取 URL,您必须存储 cookie 或 localStorage

    var firstTimeLoad = true; // Because the function will call on the initial page
    
    function iframeLoad(iframe) {
      if (firstTimeLoad) {
        firstTimeLoad = false;
        return;
      }
      alert("New page load");
    }
    &lt;iframe width="400" height="244" src="https://wooden-utensil.github.io/linkingSite1/" onload="iframeLoad(this)" frameBorder="0"&gt;&lt;/iframe&gt; &lt;!-- linkingSite1 contains a link (a href) that links to linkingSite2, and vice versa --&gt;

    【讨论】:

    • 谢谢,刷新 iframe 内容时不会调用 'onload' 下的代码。尝试使用`` ``它没有工作。
    • @DenisCandido 我右键单击 iframe 并单击“重新加载框架”,然后出现警告框。我不知道为什么它没有出现在你面前?
    • Grafana iframe 的工作方式不同。您可以与之交互,但它不会“刷新”。它确实会更新其值,但不会触发公共刷新。我不知道它是如何工作的,Grafana 社区也没有帮助我。
    【解决方案3】:

    您只需要将 iframe 的 src 设置为相同的旧 src。您可能需要添加一个带有随机数(如时间戳)的查询字符串变量以避免缓存问题。

    function refresh(){
    		var iframe = document.getElementById('myframe');
    		iframe.src = iframe.src;
    	}
    iframe{
    width:100%;
    height:300px;
    }
    <p>
    	<button onclick="refresh()">Refresh</button>
    </p>
    <iframe id="myframe" src="https://www.chartjs.org/samples/latest/charts/line/basic.html" frameborder="0"></iframe>

    【讨论】:

      【解决方案4】:

      如果您不是 iframe 中内容的所有者,您将无能为力。您可以做的最好的事情是有一个循环 (setInterval),它将根据您看到的最后一个值检查该值。

      <iframe #graph></iframe>
      
      @ViewChild('graph', { static: true }) graph!: ElementRef<HTMLIFrameElement>;
      
      private srcWatcher = new Observable(observer => {
        const interval = setInterval(() => {
          observer.next(this.graph && this.graph.nativeElement && this.graph.nativeElement.src);
        }, 10);
      
        return () => clearInterval(interval);
      }).pipe(
        distinctUntilChanged(),
      );
      

      有了这个 observable,你现在可以对它的任何变化做出反应。

      注意:如果间隔超时应该很低,我还建议 observable 应该在 zoneJS 之外运行。否则 Angular 会在每个时间间隔运行全局变化检测。全局我的意思是,它会检查整个应用程序的所有子树,使用默认的更改检测策略。

      【讨论】:

      • 不幸的是,没用。 srcWatcher 从不触发。
      • @DenisCandido 很抱歉,这是不可能的,这是一项安全功能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 1970-01-01
      相关资源
      最近更新 更多