问题描述:
当浏览器检测到非用户操作产生的新弹出窗口,则会对其进行阻止。因为浏览器认为这不是一个用户希望看到的页面。此行为根据不同浏览器和不同版本的有所不同。
场景:
需要在用户点击之后触发一个 下载文件 操作或者 打开新页面 的操作之前,需要调接口来进行判断(如权限、任务执行进度等)
解决方案
-
使用同步的ajax请求进行open前判断
优点:所有浏览器适用,无需兼容处理。
缺点:会阻塞代码执行,请求pending阶段浏览器处于假死状态;浏览器会报warning; -
使用中转页的方式,先打开新页面,待请求返回之后进行重定向或关闭
优点:目前使用较多的方式,所有浏览器适用。
缺点:无论判断是否通过都需要打开新页面;用户感知、提示不够友好
仅适用于下载:
-
适用模拟a标签点击配合魔幻的h5的download属性
优点:.....
缺点:download属性有兼容问题(canIuse中查) && download不支持跨域的资源v<火狐中实测>
不使用download的话也都会被拦截(新开target="_blank") -
不使用window.open,使用window.location.href进行下载
优点:所有浏览器适用
缺点:不能下载pdf/png等浏览器可以直接打开的资源;后台下载接口不能报错,否则会替换原有页面,体验不友好
代码:
- 使用同步的ajax请求进行open前判断
ajax('get', url, false).then(() => {
window.open('http://www.baidu.com')
})
function ajax(type, url, isAsyac) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
// 第三个参数确定是否是异步,true 异步
xhr.open(type, url, isAsyac);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4) {
resolve(xhr.response)
}
}
xhr.send()
})
}
- 使用中转页的方式,先打开新页面,待请求返回之后进行重定向或关闭
var newWin = window.open('loading page')
ajax().then(res => {
newWin.location.href = 'target url'
}).catch(() => {
newWin.close()
})
- a标签模拟点击
ajax().then(res => {
asyncOpen(res.url)
})
function asyncOpen(url) {
var a = document.createElement('a')
a.setAttribute('href', url)
a.setAttribute("target", "_blank");
a.setAttribute("download", 'name');
document.body.appendChild(a);
a.click();
a.remove();
}