【问题标题】:javascript window.open from callbackjavascript window.open 从回调
【发布时间】:2013-10-02 07:10:34
【问题描述】:

从主线程调用的window.open() 默认打开新标签。

但是,这里每次都打开新窗口(Opera 16 和 Google Chrome 29)

<input type="button" value="Open" onclick="cb1()">

<script type="text/javascript">  
function cb1() {
    setTimeout(wo, 1000); //simple async
}

function wo()
{
   var a = window.open("http://google.com", "w2");
   a.focus();
}
</script>

(哈哈,这是我对Open a URL in a new tab (and not a new window) using JavaScript的回答)。

如何在标签页中打开(默认浏览器)?

【问题讨论】:

  • 这种行为发生在什么浏览器中?
  • 希望这是你的answer
  • 所有浏览器。测试页
  • @Gurminder Singh,所有浏览器配置都是正确的(默认选项卡,不阻止弹出窗口)。如果我直接调用 wo() ,一切都很好。
  • 你试过了吗var a = window.open(url, '_blank');

标签: javascript asynchronous callback window.open


【解决方案1】:

我们遇到了同样的问题,并在 SO 周围寻找答案。我们发现的东西在我们的情况下有效,提炼出来的智慧如下:

该问题与阻止程序化窗口打开的浏览器弹出窗口阻止程序有关。浏览器允许从主线程上发生的实际用户点击打开窗口。同样,如果您在主线程上调用 window.open ,它将起作用,如上所述。根据Open a URL in a new tab (and not a new window) using JavaScript 上的这个答案,如果您正在使用 Ajax 调用并希望在成功时打开窗口,您需要设置 async: false ,因为这会将所有内容都保留在主线程上。

我们无法像那样控制我们的 Ajax 调用,但由于同样的原因,我们找到了另一个可行的解决方案。警告,它有点hacky,考虑到你的限制,可能不适合你。感谢Open a URL in a new tab (and not a new window) using JavaScript 上不同答案的评论,您在调用setTimeout 之前打开窗口,然后在延迟函数中更新它。有几种方法可以做到这一点。在打开窗口时保留对窗口的引用 w = window.open... 并设置 w.location 或使用目标 window.open('', 'target_name') 在该目标中打开的延迟函数 window.open('your-url', 'target_name') 中打开,并依靠浏览器保持参考。

当然,如果用户有在新窗口中打开链接的设置,这不会改变这一点,但这对 OP 来说不是问题。

【讨论】:

【解决方案2】:

就像其他帖子提到的那样,最好的方法是先打开窗口,然后在回调或异步函数之后设置它的位置

<input type="button" value="Open" onclick="cb1()">

<script type="text/javascript">

function cb1() {
  var w = window.open('', 'w2');
  setTimeout(function () {
    wo(w);
  }, 1000); //simple async
}

function wo(w)
{
  w.location = "http://google.com";
  w.focus();
}
</script>

或者,如果您使用异步等待,您也会遇到同样的问题。同样的解决方案仍然适用。

public async openWindow(): Promise<void> {
    const w = window.open('', '_blank');
    const url = await getUrlAsync();
    w.location = url;    
}

进一步的改进是在初始页面上打开窗口,通过加载 url 或向该页面写入一些 html 来提供一些快速反馈

public async openWindow(): Promise<void> {
    const w = window.open('', '_blank');
    w.document.write("<html><head></head><body>Please wait while we redirect you</body></html>");
    w.document.close();
    const url = await getUrlAsync();
    w.location = url;    
}

这将防止用户在解析您的 URL 所需的时间内查看空白选项卡/窗口。

【讨论】:

    【解决方案3】:

    这甚至更“hackier”但是......

    如果您将 window.open 包装在 console.log 中,那么它将起作用。

    console.log(window.open('https://someurl', '_blank'))

    【讨论】:

      【解决方案4】:

      如果新窗口作为新选项卡或新实例打开,取决于用户设置。

      【讨论】:

      • OP 表示在某些情况下它在新标签页中打开,而在其他情况下在新窗口中打开,因此他遇到的问题显然与用户设置无关。
      【解决方案5】:

      我正在使用 NestjsVue3。但我使用这里写的代码解决了它。 我刚刚在 localhost:8080 上获取了从后端发送的令牌。 所以我只是切片令牌并将其设置为本地存储,然后将用户重定向到下一页。这将授权用户使用这个tokenVue 3。 这样就解决了。你可以改进它,让它变得更好。 我就是这样做的,因为我在后端使用了 OAuth google-passport 而不是 firebase

      <script>
      
      methods: {
           googleLogin() {
            const win = window.open(
              "http://localhost:3000",
              "windowname1",
              "width=800, height=600"
            );
            const validateToken = (token) => {
              localStorage.setItem("token", token);
              this.$router.push("/GeneralPage");
              window.clearInterval(pollTimer);
              clearInterval(pollTimer);
              win.close();
            };
            const pollTimer = window.setInterval(async () => {
              try {
                let url = win.document.URL;
                let token = url.slice(22, url.length);
                if (token !== "") {
                  localStorage.setItem("token", token);
                  this.$router.push("/GeneralPage");
                  clearInterval(pollTimer);
                  win.close();
                  validateToken(token);
                  return;
                }
                return;
              } catch (e) {}
            }, 1000);
          },
      }
      </script>
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多