IOS 安全机制拦截 window.open

摘要

在ios环境,在某些情况下执行window.open不生效

一、window.open

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

  2. target:「可选参数」,它可以给以下两种值

第一种是target关键字

_self:当前标签页加载;

_blank(默认值):新标签页打开;

_parent:作为当前浏览环境的父级浏览上下文打开,没有父级浏览上下文,效果与_self相同;

_top:作为最顶级的浏览上下文打开,没有顶级浏览上下文,效果与_self相同。

第二种是一个字符串:

表示加载资源的浏览上下文的名称,也就是标签页的名称,如果这个名称在现有的标签页中不存在,则会开启一个新的标签页,如果存在,会跳转到这个标签页。

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

二、Bug

复现问题的demo:

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

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

三、原因分析

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

四、解决方案

方案1:改用location.href
javascript 复制代码
async function jump() {
  await fetch('/xxx');
  location.href = 'https://www.xxx.cn';
}

safari不会拦截location.href

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

方案2:先打开一个空标签页
javascript 复制代码
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
javascript 复制代码
async function jump() {
  await fetch('/xxx');
  setTimeout(() => {
    window.open('https://www.xxx.cn');
  }, 0)
}
javascript 复制代码
async function jump() {
  await fetch('/xxx');
  requestAnimationFrame(() => {
    window.open('https://www.xxx.cn');
  })
}

五、总结

如果setTimeout不生效,可以尝试加点延时看看,比如100毫秒,我这边实测的ios机型都能生效,所以就没加延时。

相关推荐
可乐鸡翅yeah_几秒前
hls.js 缓冲区参数 maxBufferLength、maxBufferSize 通俗讲解与业务调参
开发语言·javascript·ios·音视频·safari·m3u8
溪语流沙6 分钟前
【Web全栈进阶】PostgreSQL上手:Docker跑库 + 把早报站从SQLite迁过去
前端·docker·postgresql
IT_陈寒12 分钟前
SpringBoot自动配置的坑:你以为的捷径可能是弯路
前端·人工智能·后端
paopaokaka_luck12 分钟前
高校社团管理(AI辅助任务分配、协同过滤算法推荐、ECharts数据可视化、活动参与闭环、校园交流与反馈、器材借还管理)
java·前端·javascript·spring boot·数据分析·echarts
5008428 分钟前
React Native for OpenHarmony 实战:三方库 react-native-volume-control 的鸿蒙化适配指南
javascript·react native·react.js·electron·harmonyos
薛一半32 分钟前
React-Redux三重优化实战揭秘
javascript·vue.js·react.js
Dovis(誓平步青云)36 分钟前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物
福兮说11 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理12 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66613 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试