【问题标题】:iPhone Safari Web App opens links in new windowiPhone Safari Web App 在新窗口中打开链接
【发布时间】:2011-02-23 07:59:42
【问题描述】:

将图标添加到主屏幕后,我遇到了网络问题。如果从主屏幕启动 Web,所有链接都将在 Safari 的新窗口中打开(并失去全屏功能)。我该如何预防?我找不到任何帮助,只有同样的未回答的问题。

【问题讨论】:

  • 您现在可以在manifest.json 中使用scope 参数。有关更多详细信息,请参阅我的答案。我已经在 iOS 11.3 中对其进行了测试,它确实有效。
  • 重申一下,对于在 iOS 11.3 打开 Safari 时遇到困难的任何人,请在此处查看 @AmirRaminfar 的回答:stackoverflow.com/a/49604315/32055

标签: iphone safari iphone-standalone-web-app


【解决方案1】:

您可以简单地删除此元标记。

<meta name="apple-mobile-web-app-capable" content="yes">

【讨论】:

    【解决方案2】:

    这是一个老问题,这里的许多解决方案都使用 javascript。从那时起,iOS 11.3 已经发布,您现在可以使用scope member。范围成员是一个类似"/" 的 URL,该范围内的所有路径都不会打开新页面。

    范围成员是一个字符串,表示导航范围 此 Web 应用程序的应用程序上下文。

    这是我的例子:

    {
      "name": "Test",
      "short_name": "Test",
      "lang": "en-US",
      "start_url": "/",
      "scope": "/",
      ...
    }
    

    您还可以阅读更多关于它的信息here。我还建议使用generator,它将提供此功能。

    如果您指定范围,一切都会按预期工作,类似于 Android,范围之外的目的地将在 Safari 中打开 — 带有 返回到您的 PWA 的按钮(状态栏中的小按钮)。

    【讨论】:

    • 很遗憾,我不相信您可以将其他网站(例如其他域上的 OAuth 登录)包含在范围内。
    【解决方案3】:

    对于使用JQuery Mobile 的用户,上述解决方案会中断弹出对话框。这将在 webapp 中保留链接并允许弹出窗口。

    $(document).on('click','a', function (event) {
        if($(this).attr('href').indexOf('#') == 0) {
            return true;
        }
        event.preventDefault();
        window.location = $(this).attr('href');     
    });
    

    也可以这样做:

    $(document).on('click','a', function (event){
        if($(this).attr('data-rel') == 'popup'){
            return true;
        }
        event.preventDefault();
        window.location = $(this).attr('href');     
    });
    

    【讨论】:

      【解决方案4】:

      我找到了一个非常完整和高效的,因为它检查是否仅在独立的 WebApp 下运行,无需 jQuery 即可工作,而且也很简单,只是在 iOS 8.2 下测试:

      Stay Standalone: Prevent links in standalone web apps opening Mobile Safari

      【讨论】:

        【解决方案5】:

        我从 @rmarscher's answer 创建了一个 bower 可安装包,可以在这里找到:

        http://github.com/stylr/iosweblinks

        您可以使用 bower install --save iosweblinks 轻松安装带有 bower 的 sn-p

        【讨论】:

          【解决方案6】:

          我用于 iOS Web 应用程序的一种解决方法是,我将所有链接(它们是 CSS 按钮)表单提交按钮。所以我打开了一个发布到目标链接的表单,然后输入 type="submit" 不是最好的方法,但这是我在找到此页面之前想出的。

          【讨论】:

            【解决方案7】:

            这是 Sean 的略微改编版本,它阻止了返回按钮

            // this function makes anchor tags work properly on an iphone
            
            $(document).ready(function(){
            if (("standalone" in window.navigator) && window.navigator.standalone) {
              // For iOS Apps
              $("a").on("click", function(e){
            
                var new_location = $(this).attr("href");
                if (new_location != undefined && new_location.substr(0, 1) != "#" && new_location!='' && $(this).attr("data-method") == undefined){
                  e.preventDefault();
                  window.location = new_location;
                }
              });
            }
            

            });

            【讨论】:

              【解决方案8】:

              当目标明确设置为“_blank”时,也许您应该允许在新窗口中打开链接:

              $('a').live('click', function (event)
              {      
                  var href = $(this).attr("href");
              
                  // prevent internal links (href.indexOf...) to open in safari if target
                  // is not explicitly set_blank, doesn't break href="#" links
                  if (href.indexOf(location.hostname) > -1 && href != "#" && $(this).attr("target") != "_blank")
                  {
                      event.preventDefault();
                      window.location = href;
                  }
              
              });
              

              【讨论】:

              • 非常感谢!这是唯一适用于带有 Twitter Bootstrap 的 iOS5 的代码。但它不适用于生产。
              • 嗯,不太清楚为什么它在生产中不起作用,但我认为这是另外一回事。请告诉我!
              【解决方案9】:

              我更喜欢在独立网络应用模式下打开所有链接,除了那些具有 target="_blank" 的链接。当然是使用 jQuery。

              $(document).on('click', 'a', function(e) {
                  if ($(this).attr('target') !== '_blank') {
                      e.preventDefault();
                      window.location = $(this).attr('href');
                  }
              });
              

              【讨论】:

                【解决方案10】:

                这在 iOS 6 上对我有用(非常轻微地改编了 rmarscher 的回答):

                <script>                                                                
                    (function(document,navigator,standalone) {                          
                        if (standalone in navigator && navigator[standalone]) {         
                            var curnode,location=document.location,stop=/^(a|html)$/i;  
                            document.addEventListener("click", function(e) {            
                                curnode=e.target;                                       
                                while (!stop.test(curnode.nodeName)) {                  
                                    curnode=curnode.parentNode;                         
                                }                                                       
                                if ("href" in curnode && (curnode.href.indexOf("http") || ~curnode.href.indexOf(location.host)) && curnode.target == false) {
                                    e.preventDefault();                                 
                                    location.href=curnode.href                          
                                }                                                       
                            },false);                                                   
                        }                                                               
                    })(document,window.navigator,"standalone")                          
                </script>
                

                【讨论】:

                  【解决方案11】:

                  此代码适用于 iOS 5(它适用于我):

                  在head标签中:

                  <script type="text/javascript">
                      function OpenLink(theLink){
                          window.location.href = theLink.href;
                      }
                  </script>
                  

                  在你想在同一个窗口中打开的链接中:

                  <a href="(your website here)" onclick="OpenLink(this); return false"> Link </a>
                  

                  我从这条评论中得到了这个代码:iphone web app meta tags

                  【讨论】:

                  • 出于某种原因,我认为这是最容易理解的。
                  【解决方案12】:

                  这适用于 iOS 6.1 和 Bootstrap JS 链接(即下拉菜单等)

                  $(document).ready(function(){
                      if (("standalone" in window.navigator) && window.navigator.standalone) {
                        // For iOS Apps
                        $('a').on('click', function(e){
                          e.preventDefault();
                          var new_location = $(this).attr('href');
                          if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined){
                            window.location = new_location;
                          }
                        });
                      }
                    });
                  

                  【讨论】:

                  • +1。这实际上会在修复链接之前检查您是否正在使用网络应用程序。
                  • 适用于 iOS 8.0.2!谢谢
                  • @sean 我在 iPad 上运行了另一个 web 应用程序,它使用图像映射作为 href 并且此代码不起作用..它适用于所有其他链接。任何想法如何使此代码与图像映射一起使用?我尝试复制整个块并将$('a').on('click', function(e){` 替换为$('area').on('click', function(e){` 但这似乎也不起作用。有什么想法吗?
                  • 如果您已经在 ahref="#" 上定义了点击函数,那么您可以更具体地使用 jquery 选择器,例如$('a[href!="#"]')
                  【解决方案13】:

                  对于那些使用 Twitter Bootstrap 和 Rails 3 的人

                  $('a').live('click', function (event) {
                    if(!($(this).attr('data-method')=='delete')){
                      var href = $(this).attr("href");
                      event.preventDefault();
                      window.location = href; 
                    }   
                  });
                  

                  删除链接仍然以这种方式工作。

                  【讨论】:

                    【解决方案14】:

                    您也几乎可以正常进行链接:

                    <a href="#" onclick="window.location='URL_TO_GO';">TEXT OF THE LINK</a>
                    

                    你可以删除哈希标签和href,它所做的一切都会影响外观..

                    【讨论】:

                      【解决方案15】:

                      如果使用 jQuery Mobile,您将在使用 data-ajax='false' 属性时体验到新窗口。事实上,只要通过外部链接、$.mobile.ajaxEnabled 设置或使用 target='' 属性关闭 ajaxEnabled,就会发生这种情况。

                      你可以用这个来修复它:

                      $("a[data-ajax='false']").live("click", function(event){
                        if (this.href) {
                          event.preventDefault();
                          location.href=this.href;
                          return false;
                        }
                      });
                      

                      (感谢 Richard Poole 的 live() 方法 - 没有使用 bind())

                      如果您已全局关闭 ajaxEnabled,则需要删除 [data-ajax='false']。

                      这花了我很长时间才弄清楚,因为我原以为这是一个 jQuery Mobile 特定的问题,而实际上是 Ajax 链接实际上禁止了新窗口。

                      【讨论】:

                      • 完美,你救了我:)
                      【解决方案16】:

                      这是我将用于页面上所有链接的内容...

                      document.body.addEventListener(function(event) {
                          if (event.target.href && event.target.target != "_blank") {
                              event.preventDefault();
                              window.location = this.href;                
                          }
                      });
                      

                      如果您使用的是 jQuery 或 Zepto...

                      $("body").on("click", "a", function(event) {
                         event.target.target != "_blank" && (window.location = event.target.href);
                      });
                      

                      【讨论】:

                        【解决方案17】:

                        这里的其他解决方案要么不考虑外部链接(您可能希望在 Safari 中打开外部链接),要么不考虑相对链接(其中没有域)。

                        html5 mobile-boilerplate 项目链接到此要点,该要点对该主题进行了很好的讨论:https://gist.github.com/1042026

                        这是他们提出的最终代码:

                        <script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>
                        

                        【讨论】:

                        • 这很好用,除了一页,我们公司的“联系我们”页面。它没有显示页面,而是打开应用程序“地图”并精确定位我们的办公室。可能是什么原因造成的,我们该如何解决?
                        • @Jonathan 我不确定。如果您删除此脚本,它不会发生吗?也许发布指向您网站的链接?或者打开一个新问题,这可能会更好。
                        • @rmarscher 这只发生在运行您提供的代码时,而不是没有它。我自己是一名网络开发人员,我不明白为什么它会以这种方式处理链接。我没有页面 URL,因为它当前没有运行代码,所以您不会注意到它。此外,它也会影响常规的 Safari,而不仅仅是独立的。感谢您的回答!
                        • 这应该是公认的答案,并且通过将代码放在标题中,在我用 PHPRunner 制作的 iPad1 全屏客户端上发挥了魅力。不知道为什么它如此令人困惑,因为它看起来相当简洁的代码可以在没有太多 BW 开销的情况下清晰地编写......不过这只是很挑剔,而且通常真的想说谢谢。
                        • 这会破坏 Bootstrappy 的东西,例如 js 函数使用的 href="#" 链接
                        【解决方案18】:

                        根据 Davids 的回答和 Richards 的评论,您应该执行域检查。否则,您的网络应用中也会打开指向其他网站的链接。

                        $('a').live('click', function (event)
                        {      
                            var href = $(this).attr("href");
                        
                            if (href.indexOf(location.hostname) > -1)
                            {
                                event.preventDefault();
                                window.location = href;
                            }
                        });
                        

                        【讨论】:

                        • 对上述解决方案的良好补充。需要进行域检查以防止人们在应用中打开外部网站。此外,适用于 iOS 5。
                        • 对我来说也适用于 iOS 5。问题有时可能出在缓存上。在测试不同的方法时,我无法强制 iOS 使其缓存无效并检索新版本的 JS 文件(Safari 确实接受了更改,但在将应用程序添加到主屏幕后不再存在)。更改我的开发服务器的端口有所帮助。如果您设置了 max-age=0(或等效项),那么这可能不会影响您。
                        【解决方案19】:

                        如果你使用 jQuery,你可以这样做:

                        $("a").click(function (event) {
                            event.preventDefault();
                            window.location = $(this).attr("href");
                        });
                        

                        【讨论】:

                        • 请解释为什么 .live() 可能更好?
                        • live 会将事件绑定到所有链接,包括那些还不存在的链接,click 只会绑定到当前存在的链接
                        • 谢谢!救生员。我只是花了几个小时试图弄清楚为什么 safari 一直在加载。
                        • +1 from me - 使用 this.href 而不是转换为 jQuery 对象,但感谢您的回答。适用于 iOS6。
                        • .live() 是 deprecated as of jQuery 1.7removed as of 1.9。使用 $(document).on('click', 'a', function(){...}) 代替。
                        【解决方案20】:

                        我在iWebKit框架中找到了JavaScript解决方案:

                        var a=document.getElementsByTagName("a");
                        for(var i=0;i<a.length;i++)
                        {
                            a[i].onclick=function()
                            {
                                window.location=this.getAttribute("href");
                                return false
                            }
                        }
                        

                        【讨论】:

                        • 为了说明这一点并明确说明:iOS 将 Web 应用程序中的链接视为应在 Safari 中打开的内容,而 javascript 位置更改为允许在 Web 中使用的应用程序内操作-应用程序。上面的代码有效,因为它阻止了默认链接行为,将其替换为 js nav 调用。
                        • 有相反的例子吗?强制 iPhone Web 应用在 Safari 中打开页面,即使它是 javascript 位置更改?
                        • @Pavel 感谢您提及 iwebkit :)。有助于获得一些流量:D
                        • [].forEach.call(document.links, function(link) { link.addEventListener("click", function(event) { event.preventDefault(); window.location = this.href; }) });
                        • 这个有副作用吗?
                        猜你喜欢
                        • 2012-02-11
                        • 2020-04-22
                        • 2016-01-05
                        • 1970-01-01
                        • 2015-02-09
                        • 1970-01-01
                        • 2015-09-26
                        • 2012-02-11
                        • 2021-11-30
                        相关资源
                        最近更新 更多