背景
根据接口返回的url地址,打开新的标签页,部分用户出现浏览器拦截新窗口弹出甚至不提醒拦截弹窗的问题
原方案是在获取url之后直接使用window.open()
或window.location.href
原因
浏览器确认是用户操作的情况下,
window.open()
不会被拦截,但若是在ajax的回调里面进行window.open()
,会拦截!因为浏览器的安全策略会认为这是一个骚扰用户的行为,不同浏览器的安全级别不同,也会根据用户的设置而表现不同。
经测试,方案一、二可以解决问题,其他方案测试无效,可自行试验
方案一: 先打开新标签页之后重定向页面
该方案的问题在于会优先打开一个 空白网页,如果网速太慢会出现白屏等待,可以在窗口写入用户提示标语
async openNewTab(url: string) {
const openNewWindow = window.open('', '_blank') // 在请求之前打开一个新页面
openNewWindow.document.write('努力加载中,请稍后...')
try {
const resData = await this['$api'].get(this, url)
if (resData && resData.code === 200) {
openNewWindow.location.href = resData.url // 重定向页面URL
}
} catch (err) {
log(err)
}
}
方案二: 将Ajax请求修改成同步请求
经测试axios
框架使用async
和await
来模拟同步请求无效,需要原生Ajax请求设置为同步请求才有效
缺陷是当接口响应时间太长还是会出现拦截窗口的问题
async openNewTab(url: string) {
// 第四步,发送HTTP请求
this.ajax({
url: url, // 请求地址
type: 'GET', // 请求方式
success: function (response, xml) {
// 此处放成功后执行的代码
window.open(JSON.parse(response).url)
},
fail: function (status) {
// 此处放失败后执行的代码
}
})
}
ajax(options) {
// 第一步,创建一个XHR对象,也即一个异步调用的对象
function createXHR() {
let xhr
// 非IE6
if (typeof XMLHttpRequest !== 'undefined') {
xhr = new XMLHttpRequest()
} else if (typeof ActiveXObject !== 'undefined') {
// IE6及以下版本浏览器
xhr = new ActiveXObject('Microsoft.XMLHTTP')
} else {
xhr = null
}
return xhr
}
var xhr = createXHR()
// 第二步,设置相应HTTP请求的状态变化函数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status <= 300) || xhr.status === 304) {
options.success(xhr.responseText)
} else {
options.fail(xhr.status)
}
}
}
// 第三步,创建一个新的HTTP请求,并设置请求的方式、URL,是否异步
if (options.type === 'GET') {
xhr.open('GET', options.url, options.params, false) // 设置为同步请求
xhr.send(null)
}
}
方案三: js生成a标签,修改a标签href或自定义点击事件
①修改a标签href,模拟用户点击
async openNewTab(url: string) {
try {
const resData = await this['$api'].get(this, url)
if (resData && resData.code === 200) {
// 使用 a 标签 实现页面跳转
const RecurrenceHtml = document.createElement('a')
RecurrenceHtml.setAttribute('href', resData.url)
RecurrenceHtml.setAttribute('target', '_blank')
RecurrenceHtml.style.display = 'none'
document.body.appendChild(RecurrenceHtml)
RecurrenceHtml.click()
document.body.removeChild(RecurrenceHtml)
}
} catch (err) {
log(err)
}
}
②设置自定义点击事件,模拟用户点击
async openNewTab(url: string) {
try {
const resData = await this['$api'].get(this, url)
if (resData && resData.code === 200) {
// 使用 a 标签 模拟实现用户点击自定义事件,实现页面跳转
const RecurrenceHtml= document.createElement('a')
RecurrenceHtml.onclick = function () {
window.open(resData.url, '_blank')
}
document.body.appendChild(RecurrenceHtml)
RecurrenceHtml.click()
document.body.removeChild(RecurrenceHtml)
}
} catch (err) {
log(err)
}
}
方案四: js生成form表单,使用form.submit来访问
async openNewTab(url: string) {
const openNewWindow = window.open('', '_blank') // 在请求之前打开一个新页面
try {
const resData = await this['$api'].get(this, url)
if (resData && resData.code === 200) {
// 使用 form.submit 实现页面跳转
const form = document.createElement('form')
form.action = resData.url
form.target = '_blank'
form.method = 'GET'
document.body.appendChild(form)
form.submit()
}
} catch (err) {
log(err)
}
}