You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Tampermonkey在悬浮模态框中渲染需JS加载的第三方页面内容

解决方案

核心问题:你通过GM_xmlhttpRequest请求仅能拿到页面静态原始HTML,目标站点依赖JS渲染的动态内容不会自动生成,以下是3种可落地的实现方案,优先推荐第一种:

方案1:使用iframe嵌入(最简便)

直接在弹窗容器内插入iframe加载目标页面,iframe会自动执行页面内置JS完成渲染,无需手动处理JS执行逻辑,你只需要控制iframe的尺寸、滚动位置来露出你需要的页面区域即可。
可直接替换原有代码的对应部分:

// 替换原有弹窗插入逻辑
$("body").append ( `<div id="gmPopupContainer" style="display:none">
  <iframe id="gmPopupIframe" frameborder="0" scrolling="no"></iframe>
</div>`);

(function() {
  var bindToShowStatus = function() {
    jQuery("td#key").off( "mouseenter mouseleave" );

    jQuery("td#key").mouseenter(function(e) {
      const targetUrl = "https://review.opendev.org/c/openstack/sushy/+/819309";
      $("#gmPopupIframe").attr("src", targetUrl);
      $("#gmPopupContainer").show();
    }).mouseleave(function (e) {
      console.log("Out");
      $("#gmPopupContainer").hide();
      $("#gmPopupIframe").attr("src", ""); // 离开时清空避免后台继续加载
    });
  };

  (new MutationObserver(check)).observe(document, {childList: true, subtree: true});

  function check(changes, observer) {
    if(document.querySelector('td#key')) {
      observer.disconnect();
      console.log("Loaded");
      bindToShowStatus();
    }
  }
})();

// 替换原有样式
GM_addStyle ( `
    #gmPopupContainer {
        position:               fixed;
        top:                    30%;
        left:                   20%;
        background:             white;
        border:                 3px double black;
        border-radius:          1ex;
        z-index:                777;
        overflow: hidden;
        width: 800px; /* 按需调整可见区域宽度 */
        height: 500px; /* 按需调整可见区域高度 */
    }
    #gmPopupIframe {
        width: 1200px; /* 比容器宽,用来裁掉侧边栏等不需要的部分 */
        height: 1000px; /* 比容器高,调整偏移量露出目标区域 */
        margin-left: -200px; /* 左移裁掉侧边栏,按需调整数值 */
        margin-top: -200px; /* 上移裁掉顶部导航,按需调整数值 */
    }
` );

如果目标站点和当前脚本运行站点跨域,无法通过JS操作iframe内部DOM,调整上面的margin和宽高数值即可精准露出你要的区域,不需要操作内部DOM。

方案2:手动执行页面JS渲染(适合需要提取特定DOM的场景)

如果不想用iframe,可以把请求到的HTML里的所有script标签提取出来,放到隐藏的沙箱iframe中执行,等渲染完成后再提取目标DOM插入你的弹窗:

function processDocumentResponse (rspObj) {
    if (rspObj.status != 200 && rspObj.status != 304) {
        reportAJAX_Error (rspObj);
        return;
    }
    'use strict';
    // 创建隐藏的沙箱iframe用来执行目标站JS,避免污染当前页面
    const sandboxIframe = document.createElement('iframe');
    sandboxIframe.style.display = 'none';
    document.body.appendChild(sandboxIframe);
    // 把请求到的HTML写入沙箱iframe,会自动执行内部JS
    sandboxIframe.contentDocument.write(rspObj.responseText);
    sandboxIframe.contentDocument.close();
    // 等待JS执行完成,定时查询目标元素是否渲染完成
    const checkTimer = setInterval(() => {
        // 替换成你要提取的目标元素选择器
        const targetEle = sandboxIframe.contentDocument.querySelector('.target-class');
        if (targetEle) {
            clearInterval(checkTimer);
            // 把目标元素克隆到你的弹窗里
            document.getElementById('gmPopupContent').innerHTML = targetEle.outerHTML;
            // 删掉沙箱iframe释放资源
            document.body.removeChild(sandboxIframe);
        }
    }, 100);
    // 超时处理,10秒没渲染完就终止
    setTimeout(() => {
        clearInterval(checkTimer);
        document.body.removeChild(sandboxIframe);
    }, 10000);
}

该方案要注意目标站JS可能有跨域限制、或者检测运行环境的反爬逻辑,可能会执行失败。

方案3:调用目标站点公开接口(性能最优)

你访问的是gerrit代码评审页面,gerrit有原生的REST API可以直接拿评审数据,不需要爬页面渲染,你直接请求对应接口拿JSON数据,自己拼接成你要的HTML结构插入弹窗即可,性能比前两个方案高很多,不会有多余的资源加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 13:36:04