Sign in
Log inSign up

解决window.open弹窗被阻止问题

qianxun's photo
qianxun
·May 17, 2022·

1 min read

问题描述

本人的某个项目场景中,需要进行订单支付,点击支付按钮后会调用某个接口(使用axios),接口返回成功后,会打开支付页面,这时,在某些浏览器里(如:火狐浏览器)会提示是否阻止弹出窗口,导致窗口无法自动弹出,需要用户进行设置才能打开支付页面,如图:


原因分析:

查阅网上资料得知,当浏览器检测到非用户操作产生的新弹出窗口,就会对其进行阻止。 经本人测试,下面两种情况弹窗会被拦截:

  • 页面初始化,异步延迟执行跳转
    <body>
      <h1>订单页</h1>
    </body>
    <script>
      setTimeout(() => {
          window.open('/pay.html')
      }, 500);
    </script>
    
  • 接口请求返回中执行跳转
    <body>
      <h1>订单页</h1>
      <button>跳转支付</button>
    </body>
    <script>
      const btn = document.querySelector('button')
      btn.addEventListener('click', function () {
          // 调用接口
          axios.get('api.github.com/zen').then(res => {
              window.open('/pay.html')
          })
      })
    </script>
    

解决方案:

  • 方案1 将异步延迟跳转放到用户操作的事件中,如点击:
    <body>
      <h1>订单页</h1>
      <button>跳转支付</button>
    </body>
    <script>
      const btn = document.querySelector('button')
      btn.onclick = function() {
          setTimeout(() => {
              window.open('/pay.html')
          }, 500);
      }
    </script>
    
  • 方案2 创建a链接模拟跳转

    <body>
      <h1>订单页</h1>
      <button>跳转支付</button>
    </body>
    <script>
      const btn = document.querySelector('button')
      btn.addEventListener('click', function () {
          const a = document.createElement('a');
          const id = 'newpage'
          const url = 'pay.html'
          a.setAttribute('href', url);
          a.setAttribute('target', '_blank');
          a.setAttribute('id', id);
          // 防止反复添加
          if(!document.getElementById(id)) {
              document.body.appendChild(a);
          }
          a.click();
      })
    </script>
    
  • 方案3(推荐👍)

    查询MDN文档发现此段说明: Window.open() - Web API 接口参考 | MDN 在这里插入图片描述

根据文档说明,我们可以先创建一个未载入的空白窗口,然后等待接口返回成功后再更改其url,代码如下:

<body>
    <h1>订单页</h1>
    <button>跳转支付</button>
</body>
<script>
    const btn = document.querySelector('button')
    btn.addEventListener('click', function () {
        const newPage = window.open(); // 打开一个不被拦截的空白窗口
        // 调用接口
        axios.get('api.github.com/zen').then(res => {
            newPage.location.href = '/pay.html' // 修改空白窗口的url
        })
    })
</script>

c1.jpg

结尾

每一个不曾起舞的日子,都是对生命的辜负