昨天遇到一個很是有趣的需求場景,背景以下:咱們是一家電商平臺,常常會作一些商品的促銷專題活動。昨天我司產品經理找到我和APP的開發工程師,但願咱們解決一個問題:在APP端點擊專題活動中的商品,打開的頁面是H5頁面,而不是客戶端的原生頁面。產品經理但願打開原生頁面,以讓用戶得到更好的體驗。見下圖,左圖是在APP中打H5頁面,右圖是在APP中打開APP原生頁面。javascript
發現了問題之後,我初步瞭解了致使這個問題的緣由。原來,APP端展現的專題活動頁面和小程序同樣,採用的是webview的解決方案,即APP指定一個對象(我以爲是路徑,不過據我司APP開發工程師介紹,APP中只有對象的說法,沒有路徑的說法),接收H5頁面的連接,並將連接中的HTML鋪到APP的對象(路徑)中。用戶點擊專題中的商品連接也是一樣的方式,所以最後展現出來的商品詳情頁就是H5頁面,而不是客戶端的原生頁面。前端
我目前在公司主要是負責小程序端的。在此以前,我接觸太小程序相似的業務場景。在小程序中若是想要實現相似的邏輯,須要在H5頁面的頭部引入一段JS代碼。這段JS代碼的主要做用,是在window對象中加入一個新的名爲wx的屬性。這個屬性是一個對象,有本身的屬性和方法。經過調用wx.miniProgram.getEnv()方法,並傳入一個回調函數,即java
wx.miniProgram.getEnv(res => {
if(res.miniProgram) {
//小程序環境
let url;
wx.miniProgram.navigateTo({url: url});
} else {
//微信中打開內置瀏覽器
}
})
複製代碼
以上判斷完成以後,就完成了在小程序端跳轉到原生頁面的邏輯。android
由於有這個基礎,我下意識認爲APP端若是想要實現相似的邏輯,也須要先引入一段相似的JS代碼。但和APP工程師溝通後發現,客戶端的API已經支持了這段JS代碼須要實現的功能。我司APP工程師還給我展現了一段以前使用的代碼:ios
if(window.android) { //判斷android對象是否存在
window.android.navigateTo(url); //調用android分享
} else {
//調用ios支付方法!
window.webkit.messageHandlers.navigateTo.postMessage(url);
}
複製代碼
個人猜測是這樣的:客戶端(Android、iOS)中APP工程師經過API提供的方法,給JS的執行環境window增長了對應的屬性:Android客戶端增長的屬性是android,iOS客戶端增長的屬性是webkit。這兩個屬性都是對象,在給這兩個屬性增長對應的方法之後,就能夠直接在JS代碼中引用了。爲了證實個人猜測,我特地百度了一下「經過js調用android原生方法」,發現瞭如下這段代碼。web
//設置webview
myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JavaScriptinterface(this),"android");
myWebView.setWebViewClient(new myWebViewClient());
//建立JavaScriptinterface類
public class JavaScriptinterface {
Context context;
public JavaScriptinterface(Context c) {
context= c;
}
/**
* 與js交互時用到的方法,在js裏直接調用的
*/
@JavascriptInterface
public void showToast(String ssss) {
Toast.makeText(mContext, ssss, Toast.LENGTH_LONG).show();
}
}
//在JS中調用android原生方法
<script type="text/javascript">
function showToast() {
android.showToast("哈哈啊哈 ");
}
</script>
</head>
<body>
<input type="button" value="調用"
onClick="showToast()"/>
</body>
複製代碼
雖然沒有學過客戶端的相關知識,但這個邏輯仍是一目瞭然的。從這段代碼也能夠看出,安卓客戶端除了能夠指定方法的名稱外,還能夠指定設置在window對象下的屬性的名稱,也就是上一行代碼中的window.android。你能夠改爲window.Android、window.app,由app工程師指定。小程序
確認該屬性的名稱後,再爲這個屬性添加方法,這個方法由H5頁面的前端工程師和app開發工程師約定名字。app開發工程師實現邏輯跳轉,前端工程師直接引用,便可實現跳轉到app的原生頁面。瀏覽器
與安卓客戶端的實現邏輯同樣,蘋果客戶端也是在window對象下添加指定的屬性,在該屬性下面添加方法,便可跳轉到指定的app原生頁面。不過須要注意的是,因爲客戶端API版本的不一樣,可能引用的方式也不一樣。目前我已經接觸到了如下兩個引用方式:bash
//第一種引用方式
window.webkit.messageHandlers.shareLink.postMessage(shareData);
//第二種引用方式
window.RequiredSkill.shareLink(shareData)
複製代碼
因爲以前主要工做在小程序端,因此初次接觸該問題時,習慣性的用了小程序的處理思路。也是第一次接觸到和客戶端的JS交互方式,感受比較有意思,因此記錄下來。微信
另一個收穫是,之前一直覺得window對象就是指瀏覽器中的window;但經過解決這個問題發現,小程序、APP端也有相應的window對象,並且小程序和APP端的window對象還有獨有的屬性。想一想確實是這個道理,不一樣的瀏覽器window對象的屬性都不一樣,更況且不一樣的客戶端?