【问题标题】:How can I run a script in another (newly-opened) tab?如何在另一个(新打开的)选项卡中运行脚本?
【发布时间】:2021-12-02 00:57:38
【问题描述】:

我正在尝试在新选项卡中运行脚本。我使用的代码是这样的:

$ = jQuery;
function openAndPush(url, id) {
    var win = window.open('https://example.com' + url + '?view=map');
    var element = $('<script type="text/javascript">console.log("Starting magic...");var region_id='+id+';$=jQuery;var p=$(\'div["se:map:paths"]\').attr(\'se:map:paths\');if(p){console.log("Found! pushing..."); $.get(\'https://localhost:9443/addPolygon\', {id: region_id, polygon: p}, function(){console.log("Done!")})}else{console.log("Not found!");}</script>').get(0);
    setTimeout(function(){ win.document.body.appendChild(element); 
    console.log('New script appended!') }, 10000);
}

考虑以下几点:

  • 我在this answer 中受到启发,但改用了 jQuery。
  • 我在检查器/控制台中从https://example.com 中的另一个页面运行此代码(是的,实际域不是 example.com - 但相对于原始选项卡,目标 url 始终在同一个域中)到避免 CORS 错误。
  • 当我运行函数(例如,openAndPush('/target', 1))然后在 另一个 检查器中检查代码时,其中一个用于 new 窗口,控制台消息 Starting magic...未显示(我等待 10 秒甚至更多)。但是,新的 DOM 元素(我正在创建的这个脚本)显示在 Elements 选项卡中(并且,在 first 控制台/检查器中,我可以看到 New script appended! 消息)。

(在这两种情况下jQuery 都存在,但不占用$ 标识符,这似乎是未定义的 - 所以我手动占用它)

我的结论是我的脚本没有在新窗口中执行。

我错过了什么?如何确保代码正在执行?

【问题讨论】:

  • 我对你的第二点感到困惑。您的意思是您正在域aaa.com 上运行一个脚本,该脚本会打开一个到bbb.com 的窗口,然后添加一个&lt;script&gt;
  • 没有。域始终相同。我只是将其更改为 example.org
  • 这个答案stackoverflow.com/questions/1199676/… 似乎表明您不能按照您显示的方式进行操作,但必须构建并附加一个节点。我似乎记得脚本在作为 html 注入时没有被评估,可能是因为 DOM 没有重新加载,也没有加载和解析脚本......没有触发 onLoad 事件来获取它......或者我记得。

标签: javascript window.open


【解决方案1】:

不要在文档中嵌入脚本元素,而是这样做。

  • 将要在另一个选项卡中运行的代码包装到一个函数中。
  • 将该包装函数绑定到新标签的窗口
  • 调用该函数

这是我在控制台中运行的代码,它对我有用,即打开另一个选项卡并显示警报。

function openAndPush(url, id) {
    var win = window.open('https://www.google.com');
    win.test = function () {
        win.alert("Starting magic...");

    }
    win.test();
    setTimeout(function () {
        win.document.body.appendChild(element);
        console.log('New script appended!')
    }, 10000);
}

【讨论】:

  • 是的,你是对的。我以为我无法阅读窗口的内容,但我忘记了 CORS 策略允许我在同一个域上(至少在这种情况下)。我可以在那里安全地废弃 DOM。
【解决方案2】:

发现我的错误在于创建新脚本节点时引用的原始文档,而不是目标文档(即win.document)。我需要的是更改代码以引用新文档并直接创建节点,在 that 点的中间没有 jQuery。所以我改变了我的代码:

function openAndPush(url, id) {
    var win = window.open('https://streeteasy.com' + url + '?view=map');
    var element = win.document.createElement('script');
    element.type='text/javascript';
    element.innerHTML = 'console.log("Starting magic...");var region_id='+id+';$=jQuery;var p=$(\'div[se\\\\:map\\\\:paths]\').attr(\'se:map:paths\');if(p){console.log("Found! pushing..."); $.get(\'https://localhost:9443/addPolygon\', {id: region_id, polygon: p}, function(){console.log("Done!")})}else{console.log("Not found! searched in: ", document);}'
    setTimeout(function(){ win.document.body.appendChild(element); console.log('New script appended!') }, 10000);
}

使用这段代码,实际上发生了一些事情:JS 代码在新文档的上下文中被解析(并创建了它的节点)。较旧的替代方案涉及原始控制台(因为原始文档被隐式引用)。

【讨论】:

    【解决方案3】:

    将脚本发送到另一个网页是不好的做法。您可以使用复杂的 URL 传递一些查询参数,并通过来自另一个网页的源代码来处理它,这样会更好:

    function doMagicAtUrlByRegionId (url, regionId) {    
      window.open(`https://example.com${url}?view=map&magic=true&region_id=${regionId}`);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 2013-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多