IOS 安全机制拦截 window.open

打印 上一主题 下一主题

主题 1032|帖子 1032|积分 3096

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
摘要

在ios环境,在某些环境下实行window.open不生效
一、window.open

  1. window.open(url, target, windowFeatures)
复制代码
1. url:「可选参数」,表现你要加载的资源URL或路径,如果不传,则打开一个url地址为about:blank的空白页。
2. target:「可选参数」,它可以给以下两种值
第一种是target关键字
_self:当前标签页加载;
_blank(默认值):新标签页打开;
_parent:作为当前浏览环境的父级浏览上下文打开,没有父级浏览上下文,效果与_self雷同;
_top:作为最顶级的浏览上下文打开,没有顶级浏览上下文,效果与_self雷同。
第二种是一个字符串:
表现加载资源的浏览上下文的名称,也就是标签页的名称,如果这个名称在现有的标签页中不存在,则会开启一个新的标签页,如果存在,会跳转到这个标签页。
3. windowFeatures:「可选参数」,它是一个字符串,用来描述窗口的特性,其格式是"key1=value1, key2=value2",即将key和value以=号毗连拼接成字符串,多个key value以逗号隔开,比如我们要打开一个宽为500,高为600的窗口可以这么写:
  1. window.open(url, 'new-window', 'width=500,height=600');
复制代码
二、Bug

复现问题的demo:
  1. async function jump() {
  2.   await fetch('/xxx');
  3.   window.open('https://www.xxx.cn');
  4. }
复制代码
正常环境下实行window.open是能正常新标签页打开传入的url的,但是一旦前面用await做了异步操纵后,再实行window.open,就不生效了。
三、原因分析



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

方案1:改用location.href

  1. async function jump() {
  2.   await fetch('/xxx');
  3.   location.href = 'https://www.xxx.cn';
  4. }
复制代码
safari不会拦截location.href
并不是所有场景下都适适用location.href,由于location.href会刷新页面,所以必要根据具体场景来选择。
方案2:先打开一个空标签页

  1. async function jump() {
  2.   const newWin = window.open("", "_blank"); // 提前打开一个窗口
  3.   const { jumpUrl } = await fetch('/xxx');
  4.   if (jumpUrl) {
  5.     newWin.location = jumpUrl;
  6.   } else {
  7.     newWin.close();
  8.     // ...
  9.   }
  10. }
复制代码
这里根据有没有jumpUrl进行跳转,如果没有jumpUrl,我必要调用close方法关闭刚才提前打开的那个窗口,而如许用户就会体验到的流程就是,先出来一个新窗口,随后被秒关闭,如许用户体验很差。
方案3:setTimeout/requestAnimationFrame

  1. async function jump() {
  2.   await fetch('/xxx');
  3.   setTimeout(() => {
  4.     window.open('https://www.xxx.cn');
  5.   }, 0)
  6. }
复制代码
  1. async function jump() {
  2.   await fetch('/xxx');
  3.   requestAnimationFrame(() => {
  4.     window.open('https://www.xxx.cn');
  5.   })
  6. }
复制代码
五、总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表