window.open被浏览器拦截问题

📝 ✏️ 📌
window.open被浏览器拦截问题

使用window.open前,需要先知道一个概念:Pop-up blocker(弹窗拦截)

Pop-up blocker(弹窗拦截)目前,主流浏览器都有弹窗拦截机制,目的是为了阻止网站在非用户操作(如点击操作)时恶意弹出窗口(如弹窗广告、打开新窗口等),影响用户体验。

基于这个目的,浏览器会在用户操作时,允许同步打开弹窗;但对于异步打开弹窗操作,浏览器会判断从用户进行操作到打开弹窗的时间间隔,如果时间间隔超过它允许的时间值,就会启动拦截

参考文档:What are pop-ups

时机由上述可知,使用window.open的时机,应该是在用户操作(如点击操作)时同步调用

代码语言:javascript复制// 会被拦截

window.open('https://javascript.info');

// 不会被拦截

button.onclick = () => {

window.open('https://javascript.info');

};时间当异步使用window.open时,就需要考虑与用户进行操作的间隔时间,不同浏览器允许的间隔时间不同,我们以FireFox为例

代码语言:javascript复制// 会被拦截

button.onclick = () => {

// 间隔3s打开会被拦截

setTimeout(() => window.open('http://google.com'), 3000);

};

// 不会被拦截

button.onclick = () => {

// 间隔2s打开不会被拦截

setTimeout(() => window.open('http://google.com'), 2000);

};在不同浏览器中实际测试时间间隔为:

Chrome:小于5s(不包括5s)

FireFox:小于3s(不包括3s)

Edge:小于5s(不包括5s)

Safari:小于1s(不包括1s)

参考文档:Popups and window methods

其他方式打开新窗口网上也搜到一些使用其他方式打开新窗口的方法,但经过实际测试,在异步打开新窗口的情况下,只要超过了浏览器拦截机制允许的间隔时间,也同样会被拦截。

Chrome中测试测试代码如下:

代码语言:javascript复制// a标签形式

const windowOpenBlank = (src) => {

console.log('a标签')

let a = document.querySelector('#window-open-blank-a') as HTMLLinkElement

if (!a) {

a = document.createElement('a')

a.target = '_blank'

a.style.cssText = 'display: none'

document.body.append(a)

}

a.href = src;

a.click();

}

// form表单形式

const windowOpenByForm = (src) => {

console.log('form submit')

let $form = document.querySelector('#window-open-blank-form') as HTMLFormElement

if (!$form) {

$form = document.createElement('form')

$form.method = 'GET'

$form.target = '_blank'

$form.style.cssText = 'display: none'

document.body.append($form)

}

$form.action = src

$form.submit()

}

let count = 0

const testOpen = (link) => {

count ++

// 同步

if (count === 1) {

// 允许打开

console.log('window.open方式同步打开')

window.open(link, '_blank')

} else if (count === 2) {

// 允许打开

console.log('form表单方式同步打开')

windowOpenByForm(link)

} else if (count === 3) {

// 允许打开

console.log('a标签方式同步打开')

windowOpenBlank(link)

return

}

// 异步

setTimeout(() => {

if (count === 4) {

// 被拦截

console.log('window.open方式异步打开')

window.open(link, '_blank')

} else if (count === 5) {

// 被拦截

console.log('form表单方式异步打开')

windowOpenByForm(link)

} else if (count === 6) {

// 被拦截

console.log('a标签方式异步打开')

windowOpenBlank(link)

} else if (count === 7){

// 允许跳转

console.log('window.location.href 异步跳转')

window.location.href = link

}

}, 5000)

}异步方案1. 使用window.location.href通过上例发现,window.location.href是允许进行异步操作的,实际测试将setTimeout间隔时间设为1分钟也是不会被拦截的,所以,如果在只能异步操作,但是又得跳转链接的地方,建议使用window.location.href,比如下载附件等操作

2. 引导弹窗数据异步请求完成之后,弹出一个引导弹窗,用户点击确认按钮之后使用window.open直接跳转

弹窗广告插件浏览器一般都会有一些第三方的弹窗广告拦截插件,网上能找的大概原理如下:

针对特定弹窗广告的selector,插件通过css设置display: none;隐藏弹窗广告有的广告是通过cookie控制的,插件会注入cookie进行隐藏弹窗广告有的插件允许自定义一些过滤规则从现有查到的资料来看,异步调用window.open被拦截是浏览器自带的机制,和是否使用广告插件无关

🔗 相关推荐

✨ 💡 🎯
关于飞利浦医疗科技
bt365体育网址

关于飞利浦医疗科技

📅 01-17 👀 307
煲汤什么时候放盐?先放还是后放?大厨:都不对,这样放健康
闪电回租下款口子多久到账,公布五个各种贷款平台