前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >window.open被浏览器拦截问题

window.open被浏览器拦截问题

原创
作者头像
用户4619307
修改2023-05-04 17:21:35
3.3K2
修改2023-05-04 17:21:35
举报
文章被收录于专栏:TangPiece

使用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直接跳转

弹窗广告插件

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

  1. 针对特定弹窗广告的selector,插件通过css设置display: none;隐藏弹窗广告
  2. 有的广告是通过cookie控制的,插件会注入cookie进行隐藏弹窗广告
  3. 有的插件允许自定义一些过滤规则

从现有查到的资料来看,异步调用window.open被拦截是浏览器自带的机制,和是否使用广告插件无关

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Pop-up blocker(弹窗拦截)
  • 时机
  • 时间
    • 其他方式打开新窗口
    • 异步方案
      • 1. 使用window.location.href
        • 2. 引导弹窗
        • 弹窗广告插件
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档