百度了好久找到了一篇非常完整的帖子
前提
首先,我們可以先看知乎上的一個討論: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