解决window.open弹窗被阻止问题
问题描述
本人的某个项目场景中,需要进行订单支付,点击支付按钮后会调用某个接口(使用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>
结尾
每一个不曾起舞的日子,都是对生命的辜负