记录---当window.open被ios安全机制拦截,我掏出3种方案,终于跳转成功!

news/2025/1/22 17:00:45/文章来源:https://www.cnblogs.com/smileZAZ/p/18686431

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

一、前言

今天在开发H5的时候,遇到了一个bug,就是在ios环境,在某些情况下执行window.open不生效,所以正好趁此机会研究了一下window.open

二、window.open介绍

open方法的调用方式可以看出,open方法是定义在Window接口上,正因为如此它有三个参数:

window.open(url, target, windowFeatures)
  1. url:「可选参数」,表示你要加载的资源URL或路径,如果不传,则打开一个url地址为about:blank的空白页。

顺便介绍一下,about:blankchrome浏览器的一个命令,该指令会打开浏览器的一个内建空白页面,而不是从网络上下载,类似的命令还有about:downloadsabout:extensionsabout:history等等,具体chrom浏览器提供了哪些命令,你可以通过在浏览器地址栏输入about:about查看。

  1. target:「可选参数」,它可以给以下两种值。
    • 第一种是target关键字
      • _self:当前标签页加载;
      • _blank(默认值):新标签页打开;
      • _parent:作为当前浏览环境的父级浏览上下文打开,没有父级浏览上下文,效果与_self相同;
      • _top:作为最顶级的浏览上下文打开,没有顶级浏览上下文,效果与_self相同。
    • 第二种是一个字符串:表示加载资源的浏览上下文的名称,也就是标签页的名称,如果这个名称在现有的标签页中不存在,则会开启一个新的标签页,如果存在,会跳转到这个标签页。

这里顺便提一下,我在平时开发中曾经写出这样的代码:

const handleClick = () => {window.open(url, 'blank');
}

这个方法是绑定在一个点击按钮上面的,结果我的同事在点击多次这个按钮时,第一次会打开一个新窗口,而后续的点击都跳转到第一次点击打开的那个窗口,于是我去排查了一下,发现自己把_blank写成了blank,于是浏览器把它解析成了标签页的名字,而不是target关键词,我那时候感觉挺有意思,第一次详细去了解了这个target

  1. windowFeatures:「可选参数」,它是一个字符串,用来描述窗口的特性,其格式是"key1=value1, key2=value2",即将keyvalue=号连接拼接成字符串,多个key value逗号隔开,比如我们要打开一个宽为500,高为600的窗口可以这么写:
window.open(url, 'new-window', 'width=500,height=600');

它可以描述如下窗口特性:

  1. width:内容区域宽度,最小值为100,
  2. height:内容区域高度,最小值100,
  3. left:距离用户操作系统工作区左侧的距离,
  4. top:距离用户操作系统工作区顶部的距离。
  5. ...

这四个应该是最常用的,其它的不太常用我这里就不列举了。

至于这个windowFeatures的作用呢,平常开发中用的不太多,我能想到的场景就是比如你要通过url打开一个预览页面,让用户看里面的一些内容,就可以用这个试试。

三、bug复现

先写一个能复现问题的demo:

async function jump() {await fetch('/xxx');window.open('https://www.xxx.cn');
}

正常情况下执行window.open是能正常新标签页打开传入的url的,但是一旦前面用await做了异步操作后,再执行window.open,就不生效了。

然后我又尝试了a标签,发现效果也是一样的,无法打开新标签页。

async function jump() {await fetch('/xxx');let a = document.createElement('a');a.setAttribute('target', 'blank');a.href = 'https://www.xxx.cn';a.click()a = null;
}

四、原因分析

  1. 安全机制拦截:IOS的Safari浏览器为了防止恶意网站通过window.open/a标签打开其他网站,于是对它们的调用有所限制,如果不是由用户直接交互触发的,而是由程序自动触发的,Safari会拦截这个操作。
  2. 异步操作:在AJAX回调中执行window.open/a标签跳转,被浏览器认为是非用户交互行为,所以被拦截。

五、解决方案

方案1:改用location.href

既然window.opena标签跳转不行,那就换成location.href就好了,因为safari不会拦截location.href

async function jump() {await fetch('/xxx');location.href = 'https://www.xxx.cn';
}

当然并不是所有场景下都适合用location.href,因为location.href会刷新页面,所以需要根据具体场景来选择。

方案2:先打开一个空标签页

通过window.open("", "_blank")先打开一个空标签页,然后等待请求完成后,修改这个新标签页的url。

async function jump() {const newWin = window.open("", "_blank"); // 提前打开一个窗口const { jumpUrl } = await fetch('/xxx');if (jumpUrl) {newWin.location = jumpUrl;} else {newWin.close();// ... }
}

但这里有个体验问题,我这里根据有没有jumpUrl进行跳转,如果没有jumpUrl,我需要调用close方法关闭刚才提前打开的那个窗口,而这样用户就会体验到的流程就是,先出来一个新窗口,随后被秒关闭,这样用户体验很差。

方案3:setTimeout/requestAnimationFrame

在我的业务场景中,是必须要用window.open的,所以只能另寻他法,最终找到了一个解决方案,就是在window.open之前加一个setTimeout,在回调中执行window.open,这样就能避免被safari拦截。

async function jump() {await fetch('/xxx');setTimeout(() => {window.open('https://www.xxx.cn');}, 0)
}

后面测试了一下,发现requestAnimationFrame也可以。

async function jump() {await fetch('/xxx');requestAnimationFrame(() => {window.open('https://www.xxx.cn');})
}

六、最终我采取的方案

我最终是通过方案3setTimeout解决了问题,如果setTimeout不生效,可以尝试加点延时看看,比如100毫秒,我这边实测的ios机型都能生效,所以就没加延时。

七、小结

本文主要介绍了window.open的用法,以及我自己在平时开发中踩的坑,希望对大家平常开发有帮助!

本文转载于:https://juejin.cn/post/7461206556300607525

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/873311.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C. Gawr Gura

小鲨鱼cos本来有三张但是被审核夹了,只发两张试试..?

马拉车 Manacher

讲解马拉车算法,模板例题与代码更新日志 2025/01/22:开工。思路 马拉车算法用于解决回文子串问题,思路类似于Z函数。 首先我们考虑使所有回文串都是奇数串,具体的,我们在两两字符之间插入相同的特殊字符,比如: \[\texttt{abcba}\rightarrow\texttt{\#a\#b\#c\#b\#a\#} \…

折腾笔记[10]-使用rust进行ORB角点检测

打包ORB算法到bye_orb_rs库,使用rust进行ORB角点检测. Package the ORB algorithm into the bye_orb_rs library, and use Rust for ORB corner detection.摘要 打包ORB算法到bye_orb_rs库,使用rust进行ORB角点检测. Package the ORB algorithm into the bye_orb_rs library, a…

DBSyncer开源数据同步中间件

一、简介 DBSyncer(英[dbsɪŋkɜː(r)],美[dbsɪŋkɜː(r) 简称dbs)是一款开源的数据同步中间件,提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景。支持上传插件自定义同步转换业务,提供监控全量和增量数据统计图、应用性能预…

幻想 实在 自我

小 C 和 小 Y 的故事还未停止 …… 或许不会停止弥晨时间仓促,如有错误欢迎指出,欢迎在评论区讨论,如对您有帮助还请点个推荐、关注支持一下

AT+CSQ 和 AT+QENG查询的 RSSI不一致

1. 查询结果如下:2. CSQ查询的RSSI 接收信号强度指示时是31,对应但是 AT+QENG查询的是-128

记录printf的一个小问题

因为打算使用sprintf来格式化字符串,然后显示,遇到了一个符号类型的问题 printf("%d",now_adc);这一句,如果now_adc是uchar类型,输出字符会显示异常,后来了解到,如果要直接打印uchar只能用%x或者%s 所以如果不想改变量大小可以在前面加括号强转如printf("…

工业人工智能白皮书2025年:边缘AI驱动,助力新质生产力报告汇总PDF洞察(附原数据表)

原文链接:https://tecdat.cn/?p=38940 在当前科技变革的浪潮中,工业领域正经历着深刻转型。人工智能与工业互联网等前沿技术的迅猛发展,为工业的升级演进带来了前所未有的机遇与挑战。 本报告汇总洞察聚焦工业领域的变革趋势,深入剖析其核心驱动力与发展脉络。通过对工业 …

【视频】R语言支持向量分类器SVM原理及房价数据预测应用及回归、LASSO、决策树、随机森林、GBM、神经网络对比可视化

全文链接: https://tecdat.cn/?p=38830 原文出处:拓端数据部落公众号 分析师:Yuqi Liu 在大数据时代,精准的数据分类与预测对各领域的发展至关重要。超平面作为高维空间中的关键概念,可将线性空间一分为二,为数据分类奠定了理论基石。基于此发展而来的最大边缘分类器,…

【信息化】一个IT主管/经理/总监的该做什么?-读图解 CIO 工作指南上半IT管理总结

在这个IT人日益技术焦虑的年代,为了缓解一下学习的焦虑,看各路推荐开始学习一下《图解CIO工作指南》。我的初衷很简单,学习一下IT架构设计的思路,日常IT管理工作怎么优化,以及未来MBA毕业写IT规划论文。 一开始,当我拿到这本看似“老旧”的书籍时,心里确实犯了点嘀咕…

LCD-RGB屏幕学习(二)ESP32驱动RGB屏幕

ESP32是国内比较火的IOT芯片厂商,在个人玩家圈子里备受好评1.器件准备40pin RGB 通用接口屏幕这里的通用接口指的是市面上最常见的接口,并不属于某种标准 我拆开了吃灰已久的树莓派便携HDMI屏幕,在屏库上查看此型号,刚好满足需求,又剩下一笔大洋ESP32N16R8选用带有pasram的…

OM6621F低功耗低成本蓝牙芯片支持BLE5.1和2.4G私有协议集成了电源管理单元(PMU)BMS电池管理领域首选方案

OM6621Fx是一款专为蓝牙低功耗和专有2.4GHz应用设计的功率优化的真系统级芯片(SOC)解决方案。它集成了高性能和低功率的射频收发器,具有蓝牙基带和丰富的外围I0扩展。OM6621Fx还集成了电源管理单元(PMU),以实现高效率的电源管理。它针对2.4GHz蓝牙低功耗系统、专有2.4GHz系统…