添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

window.open(url, '\_blank') 可以打开新的窗口,但是在异步的时候使用就出现问题了

async myButtonClick(){
     let url = await this.CopyData(this.data, val);
     // after: 5000ms
      if(url) {
          window.open(url,'_blank');

像这种情况,就偶尔可以直接跳转,偶尔会被浏览器拦截:

这样很影响用户体验呀!!!

找解决办法

1. 没有用:通过创建a标签

在请求完成后 a.click(), 用来骗浏览器模拟用户点击。

async myButtonClick(){
     let url = await this.CopyData(this.data, val);
     if(url) {
         var $a = $('<a>', { href: str,  target: '_blank'});
         this.$refs.themeMy.append($a);
         $a.click();
// 这种情况并没有用,还是会被拦截

2. 没有用:调用链的深度也是一个因素

尽可能保持浅层以避免弹出窗口阻止程序。

// 之前
$('#myButton').click(function() {
    this.getJson()
getJson() {
    this.CopyData()
CopyData() {
     let url = await this.CopyData(this.data, val);
      window.open(url,'_blank');
// 更改
$('#myButton').click(async function() {
    let url = await this.getJson()
     window.open(url,'_blank');
// 这样浅了把,but 并没有什么用, 还是会拦截

也就是堆栈深度与弹出窗口阻止程序并没有任何关系。

3. 有用但不好用:提前 window.open

更改控制流以首先打开窗口(同步),然后执行 AJax 请求(异步),然后使用响应显示错误消息或执行重定向。

$('#myButton').click(async function() {
     let newTab = window.open('');
     let url = await this.getJson()
     newTab..location.href = url;

从代码可知是提前给打开了新的空白的窗口,注意哦是空白的,用户需要在空白页傻等~ 等待重定向,也不知道那个小天才想出来的,我佩服 但实际是不敢这么用的。

1. window.open()的Api

以上就是网上的都没用,怎么办呢,我先去查查window.open()的Api,发现这个是有返回值的,如果调用失败,返回值会是 null 。我测试了一下,当拦截的时候确实返回值是空的。ok 现在拿到了第一个有用的是信息了,

通过 window.open()的Api ,我能知道什么情况下是没有跳转成功、失败返回值会是 null 

2. 分析为什么偶尔拦截

既然是异步,我就用setTimeout()进行模拟请求时长

myButtonClick(){
     setTimeout(() => {
         window.open('sdf', '_blank')
    }, 6000)

发现当我设置成5秒的时候都会被拦截,当我设置成2秒的时候都会成功。

所以我猜测浏览器的弹窗机制的原因:

如果window.open从 javascript 调用或类似的调用,过了规定的时间,就会判定为不是由直接用户操作调用,则弹出窗口阻止跳转。

已经知道了弹窗机制就是过了一定时间就会阻止,这是浏览器特意的安全机制,那我们就更多的从业务上入手吧。

1. 把默认跳转改为通过弹框询问用户是否进行跳转?

既然第一次点击的时候需要请求那么久,那我们可以在接收到值得时候,

在弹出一个步骤,来提示(询问)一下用户是否进行跳转或者一个“下一步”按钮。

async myButtonClick(){
     let url = await this.CopyData(this.data, val);
     this.openNewAlert(url)
// 显示弹窗
openNewAlert(url){
    // 点击'是'的回调 window.open(url,'_blank');
    // 点击'否'的回调 关闭弹窗

2. 提示用户被拦截了

通过 window.open()的Api ,我能知道什么情况下是没有跳转成功,所以可以对失败的时候进行一个提示。

async myButtonClick(){
     let url = await this.CopyData(this.data, val);
     if(url) {
        let  windowObjectReference =  window.open(url,'_blank');
        if(windowObjectReference == null) {
            alert('页面跳转已被浏览器拦截');

3. 提示用户被拦截了, 并提供跳转

在上一个的基础上添加一个更友好的交互,来让用户点击跳转

// Message 为elment-ui的全局方法,如果使用其他ui组件可参考改造
if(windowObjectReference == null) {
            Message({
                    type'warning',
                    customClass:'myherf',
                    dangerouslyUseHTMLString:true,
                    message: `页面跳转已被浏览器拦截,点击允许本次<a href=`+ str +` target='_blank' onclick="(function(){document.getElementsByClassName('myherf')[0].remove()})()">跳转</a>`,
                    duration0,

MDN: window.open()

Stackoverflow:Avoid browser popup blockers

Stackoverflow:Bypass popup blocker on window.open when JQuery event.preventDefault() is set

Stackoverflow:Chrome window.open after ajax request acts like popup

天真的小郭 12.6k
粉丝