解决safari浏览器拦截window.open

现象

最近在做项目的时候碰到了使用window.open被浏览器拦截的情况,虽然在本地的环境可以对浏览器设置操作,但是对用户来说,不能要求用户都来通过拦截。

可以发现,当window.open为用户触发事件内部或者加载时,不会被拦截,一旦将弹出代码移动到ajax或者一段异步代码内部,马上就出现被拦截的表现了。

原因

一般情况下,如果直接在js中调用window.open()函数去打开一个新窗口,浏览器检测到的是非用户操作产生的新弹出窗口,就会对其进行阻止。因为浏览器认为这可能是一个广告,不是一个用户希望看到的页面。

window.open('//www.baidu.com', '_blank');

浏览器	ie8	chrome 40	firefox 34	opera 27	safari 5.1.7是否阻止弹出	N	N	Y	Y	Y

经过查阅资料,总结以下5个方案,目前采用的是方案2

  1. 方案一:而对于如下代码:

    document.body.addEventListener('click' function() {
        window.open('//www.baidu.com, '_blank');
    });
    

    优点:所有浏览器都不会拦截
    缺点:只要点击页面元素都会进行跳转,不是很友好

  2. 方案二:使用a标签替代,代码如下

     const a = document.createElement('a');
     a.href = location.origin+'adress'
     document.body.appendChild(a)
     a.click()
     document.body.removeChild(a)
    

    优点:模拟a标签,利用a标签的href进行页面的跳转,兼容所有浏览器
    缺点:需要创建a标签

  3. 表单提交的方式

    		const form = document.createElement('form');
    		form.action = 'www.baidu.com?id=1';
    		form.target = '_blank';
    		form.method = 'POST';
    		document.body.appendChild(form);
    		form.submit();
    

    如果需要传递参数时,需要使用 POST 方法, 默认的 GET 方法无法传递参数。也就是新页面的url中 没有参数部分。

  4. 通过JS打开新窗口会被拦截,换一种实现方式(与5相似,5是放在异步执行之后在页面跳转)

    	const tempPage=window.open('_blank'); // 先打开一个空页面
    	tempPage.location='http://www.baidu.com'; //目标的页面地址
    
  5. 先弹出窗口,然后重定向

    建议在打开第一个地址的时候给出一个类似‘当前页面正在加载中,请稍后…’的简单提示,可以避免打开两次真正的目标页面,让用户察觉到页面的重定向。

     dom.addEventListener('click', function () {
          
          
    	 const tempPage = window.open('loading page');
    	     ajax().done(function() {
          
          
    	         // 重定向到目标页面
    	          tempPage.location.href = 'target url';
    	      });
    	 });
    

猜你喜欢

转载自blog.csdn.net/qq_34574204/article/details/121821538