我们为什么禁用window.open

场景

在产品的设计中,常常会有这样的场景,创建一个文档,同时在浏览器的新tab中自动打开这个文档进行编辑。

常见实现

先发送ajax请求去创建文档,然后生成编辑文档的url在新tab中跳转。

$.ajax({
    url: '/document/create',
    type: 'post' 
}).done(function(res, status){
    var docId = res.document.id;
    window.open('/document/'+docId+'/edit','_blank');
})

问题

鉴于浏览器自身的安全策略,很多情况下,这样的跳转会受到阻止,例如:IE下通常会提示“阻止了一个弹出窗口”,不少现代浏览器也会进行阻止。大家应该还很多年前,我们在浏览网站时,常常会有一些流氓网站弹出很多小广告的窗口。

解决方案

  1. 最合理的方式应该是,创建文档后,在网页上创建一个<a href="/document/103843/edit" target="_blank"></a>的链接,让用户去点击触发跳转。
  2. 仅针对IE以外的部分现代浏览器,如chrome。可以使用同步的ajax请求,即async:false,同时要确保,同步请求的时间不能超过1s。从元素的点击事件发生开始到window.open的时间如果超过1秒,浏览器同样会进行弹出窗口的拦截。
  3. 基于2,每个ajax的请求时间是无法保证的,受制于网络延时、带宽等各个方面。所以又了另外一种写法,如下
var win = window.open('', '_blank')
$.ajax({
    url: '/document/create',
    type: 'post' 
}).done(function(res, status){
    var docId = res.document.id;
    win.location.href='/document/'+docId+'/edit';
})

综上,我们可以看出解决方案1才是相对完美的。window.open终究是违反浏览器的安全策略的,所以我们常常在前端开发中,禁用这个方法。