百度了好久找到了一篇非常完整的帖子
前提
首先,我们可以先看知乎上的一个讨论:iOS9中『经浏览器唤起APP』的最佳实现方案是怎样的?,看了这个问题,那么我们就对于接下来要做的事情,有了一些基本的概念了。
兼容性
在前两年,IOS9
,Android5
之前(具体版本不清楚),有一个还不错的解决方案是使用iframe
配合时间差的方式来唤起APP
,然后在本页内,做定时处理,也就是在前面文章中,第二条的描述。因为在大多数(不确定是不是所有移动设备都这样,不过我认为可以放弃不支持的那些)的移动设备中,如果浏览器进入后台运行,那么在浏览器内部的JS
,也会停止执行,所有当你再回到浏览器时,会有时间差的概念,以这个时间差,可以来分辨是否已经成功打开了APP
,然后再可以继续做接下来的逻辑。
那么之前为什么会使用iframe
,而没有直接使用location.href
呢?location.href
虽然在IOS
下的表现与使用iframe
没有太大的区别,但是在Android
的一些机型上,会直接跳转到一个错误页,所以,在这个时候,只能使用iframe
的了。
第二,这是当时的另外一种解决方案,那就是两者都跳转,先尝试打开APPurl
,然后当前页面也跟着跳转。这个方案我当时在好些个网站都看到了该方法,它有一个好处就是,不会出现页面假死的状态,也有一个坏处就是,会浪费用户的流量。
既然说到兼容性,那么就说明上面的方法,现在已经出现问题了,是的,前端开发者一般最怕的就是浏览器的兼容问题(现在好多了,至少不需要兼容IE6
了),以前是浏览器的兼容,现在又加了客户端的兼容了,比如这里,IOS9
和Android5
版本之后,浏览器想要打开APP
,是需要用户去手动确认的,主要是一种安全机制,防止恶意代码,不受限制的去打开APP
,对于用户来说,这是一个更安全的机制,但是对应开发来说呢?
这个提示图就是这样的:(直接引入的知乎中的一张图)
同样上面的需求,同样上面的两种解决方案,就会出现这样的问题:
1:iframe
的计时已经结束了,用户并未点击确认按钮,然后页面直接跳转了。
2:直接跳转的方式更是直接完蛋,这个提示打开APP的弹框刚出来,直接页面跳转,弹框没有了。
这就是现在存在的问题,只是在网上,一直没有找到好的解决方案,但是又不能放任该问题存在,所以这里给出一个折中的方案。
新的方案
在说新方案前,先来说一说,解决过程中,有哪些问题:
1:浏览器端无法检测是否安装有某个APP
。
2:客户端的安全机制,弹出的确认框,它是浏览器的底层行为,不会阻塞JS
的运行,也无法通过JS
调用浏览器的接口,来判断该弹出层的状态。
那么我们根据上面的内容,来提出一些新的解决方案,就像平时做兼容性处理一样,可以根据客户端的版本来做不同的处理。
在IOS9
之前和Android5
之前的版本,依然使用之前的方法,这里说的之前的方法,就是使用iframe
配合时间差来做判断,或者是页面跳转的同时,也打开APP
。
那么对应之后的版本呢,这里就要判断一下了,时间差判断的解决方案,基本是行不通的了,因为这牵扯到了用户的反应过程,那么这个时间差就不好设置了。太短了不行,如果有APP
的话,可能用户还没有操作,这边就执行来页面的跳转;太长了也不行,如果没有APP
的话,页面会在这里假死一段时间,用户体验也是不好。
那M站的URL
和APP
的URL
同时跳转,这个不可用的原因,前面也说过了。
那是否有一个稍微好一些的解决方案呢,这个我们可以按照前面解决方案中,进行一些小的改动,比如把两者合并,两个URL
同时跳转,但是M站的URL
直接使用iframe
来显示,而这个iframe
直接覆盖全屏,这样OK吗?
虽然还是比较消耗用户的流量,但却解决了一下用户体验方面的问题。至少页面不会出现假死,而且当用户安装有APP
时,可以把一部分用户量,导入到APP
中去。
到了这里,这个解决方案基本差不多了,但是这个时候,如果我想要返回,要怎么返回呢,因为是iframe
显示的另外一个新页,那么就有一个问题,返回是无法再返回原来的页面了,这样又会带来另外的体验问题,所以呢,这里我们就可以使用另外一个新的(挺老的)浏览器熟悉,history.pushState
属性,这样不管是在点击IOS
的浏览器返回,还是Android
的浏览器返回和客户端返回,都可以会触发window.onpopstate
的回调函数,那么在这个回调函数中,我们把之前显示的iframe
更新掉就OK了。
其实到这里,基本就把这个问题的一个取巧的解决方案说完了,下面就直接看个示例吧。
PC端看源码链接:http://zhangyunling.com/study/2016/20161112/index.html